2013-11-23 51 views
3

當我嘗試將實體插入到與已存在於數據庫中的另一個實體具有關聯性的數據庫中並且該實體框架中已插入關聯實體時。這會導致關聯實體的重複條目。在Repository類插入與關聯的實體會導致重複關聯

插入方法

public T Insert(T entity) 
{ 
    DbSet.Add(entity); 
    Context.SaveChanges(); 
    return entity; 
} 

通話插入方法

這發生在我的代碼某處。我將它保存到我的會話變量中。

using(var repository = new Repository<User>()) 
{ 
    user = repository.GetById(id); 
} 

然後其他一些地方:

Post post = new Post{ User = user, Content ="oO" }; 

using (var rep = new Repository<Post>()) 
{ 
    rep.Insert(post); 
} 

我解決了下面這個片段重複插入。有沒有比投射每個實體類型並重新連接相關實體更好的方法?

if (entity is Post) 
{ 
    Post post = (Post)(object)entity; 
    Context.Users.Attach(post.User); 

} 
+0

向我們顯示您的代碼。 –

+0

我同意,這需要代碼。但是從我的頭頂開始,我會說你從不同的對象上下文中添加了現有的相關實體... –

+0

向我們展示一個簡單但完整的工作示例。 – Silvermind

回答

0

最有可能你的資料庫創建上下文,而不是共享一個的新實例。這就是爲什麼Post存儲庫中新創建的上下文不「查看」用戶對象實例。

通過控制上下文的生命週期並將相同實例注入同一工作單元的不同存儲庫來正確地解決此問題。

編輯:基於容器的注入可以幫助您很多,但首先將數據上下文作爲您的存儲庫所需的構造函數參數。然後,想想你的背景的一生。

在Web應用程序中,請求生命週期通常最方便。在WPF應用程序中,您可能有一個視圖模型生存期,每個視圖模型中都有一個新的上下文。

並且容器是否滿足依賴關係是另一回事。

+0

您能舉個例子嗎?我的應用程序是否應該處理這個單個實例,或者是否有像基於容器的注入上下文的東西? –

+0

編輯我的答案。 –

0

這些通用存儲庫已不存在。有許多理由不使用它們。這是其中之一。知識庫表明你服從單一責任原則,但他們不服從。它們包含「特洛伊木馬」DbContext,這是一個比普通存儲庫應該具有更多責任的組件。因此,當存儲庫保存其「自己的」實體時,任何舊時刻它都會通過保存其他實體而脫節。

通過扔掉這個無用的圖層讓您的生活變得更輕鬆。 A DbSet是一個存儲庫,DbContext是一個工作單元。 (我在這裏只有quoting)。在EF體系結構中,UoW包含存儲庫,這些存儲庫沒有保存責任! UoW有。

刪除這些通用信息庫,你可以簡單地做

using(var db = new MyContext()) 
{ 
    var user = db.Users.Find(id); 
    Post post = new Post{ User = user, Content ="oO" }; 
    db.Posts.Add(post); // User is not added because it is known to the context. 
    db.SaveChanges(); 
} 

這是節省了連接到用戶後的專用方法。嘗試爲此創建一些通用方法毫無意義,因爲它是一個特定的任務(或用例)。正如你已經注意到的,當試圖推廣這些任務時,如果不檢查對象並引入醜陋而笨拙的ifswitch鏈,你可能無法做到這一點。