2011-04-09 174 views
1

說我有兩個實體,每個實體約20屬性和像這樣一個多到多關係:與實體框架許多一對多插入

User (Id int,Name string, .......) 
Issue (Id int,Name string, .......) 
IssueAssignment (UserId,RoleId) 

我想創建一個新的問題和分配它給一些現有的用戶。如果我有這樣的代碼:

foreach(var userId in existingUserIds) 
{ 
    int id = userId 
    var user = _db.Users.First(r => r.Id == id);   
    issue.AssignedUsers.add(user);  
} 

_db.Users.AddObject(user); 
_db.SaveChanges(); 

我注意到,當我對我的SQL數據庫運行它似乎效率非常低效。如果我看 SQL事件探查它做以下幾點:

  1. SELECT TOP(1)* FROM用戶其中userid =用戶id
  2. SELECT * FROM IssueAssignment ON User.Id =用戶id
  3. INSERT INTO用戶....
  4. INSERT INTO IssueAssignment

我的問題是:
(一)爲什麼(1)和(2)必須在所有發生的呢?
(b)(1)和(2)都會帶回所有字段,我需要做一個對象投影來限制 字段,這看起來像是不必要的工作。

感謝您的幫助

回答

4

我對你有一些可能的線索:

  1. 這是EF的行爲。 _db.Users實際上是查詢並且在查詢上調用First意味着在數據庫中執行查詢。
  2. 我想你正在使用T4模板的EFv4,並打開延遲加載。 T4模板創建能夠修復其導航屬性的「聰明」對象,因此,一旦將User添加到Issue,它會在內部觸發修正,並嘗試將Issue也添加到User。這反過來會觸發延遲加載與用戶有關的所有問題。

所以訣竅是使用虛擬對象,而不是真正的用戶。你知道這個id,你只想在新問題和現有用戶之間建立關係。試試這個(適用於EFv4 +和POCOs):

foreach(var userId in existingUserIds) 
{ 
    var user = new User { Id = userId }; 
    var _db.Users.Attach(user); // User with this Id mustn't be already loaded  
    issue.AssignedUsers.Add(user);  
} 

context.Issues.AddObject(issue); 
context.SaveChanges(); 
+0

謝謝拉迪斯拉夫,現場答案。所以附加技巧的上下文認爲用戶已經加載? – 2011-04-10 11:01:35

+0

是的。這是在多對多關係中起作用的技巧。 'Attach'使用戶知道上下文。 – 2011-04-10 11:03:30