2014-06-06 16 views
3

添加相關的實體,而無需使用我有以下類,用於測試設置導航屬性

public class Company 
{ 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

public class Employee 
{ 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 

    public string Name { get; set; } 

    public int CompanyId { get; set; } 
    public virtual Company Company { get; set; } 
} 

public class EFTestDbContext : DbContext 
{ 
    public DbSet<Employee> Employees { get; set; } 
    public DbSet<Company> Companies { get; set; } 
} 

爲了測試的緣故,我想插入一個公司,一個員工爲公司單一的SaveChanges打電話,像這樣:

Company company = new Company 
{ 
    Name = "Sample company" 
}; 

context.Companies.Add(company); 

// ** UNCOMMENTED FOR TEST 2 
//Company company2 = new Company 
//{ 
// Name = "Some other company" 
//}; 
//context.Companies.Add(company2); 

Employee employee = new Employee 
{ 
    Name = "Hans", 
    CompanyId = company.Id 
}; 
context.Employees.Add(employee); 

context.SaveChanges(); 

即使我不使用導航性能,而是我做了相關標識,這在某種程度上神祕的工作 - 僱員被保存適當的外鍵的公司,得到了從0更新爲真正的價值,這讓我走了?!?!一些隱藏的C#功能?

然後我決定添加更多的代碼,這在代碼段評論的上方,使得它被插入2×公司實體和1×Employee實體的,然後我得到異常:

無法確定'CodeLab.EFTest.Employee_Company'關係的主體結尾。多個添加的實體可能具有相同的主鍵。

這是否意味着在外鍵爲0的情況下,並且在同一個SaveChanges事務中插入了一個匹配實體時,實體框架會假定外鍵應該用於該匹配實體?

在第二個測試中,當有兩個實體與關係類型匹配時,實體框架將拋出​​一個異常,因爲它無法確定與哪個公司員工應該關聯。

編輯:

我做了第二次檢查,並註釋掉一行。第一個測試仍然正常運行(因爲int的默認值爲0):

Employee employee = new Employee 
{ 
    Name = "Hans", 
    //CompanyId = company.Id // * no need for this at all 
}; 
+1

上次編輯更好地表明,明確設置引用是絕對必要的。這可能會導致意外的行爲。人們甚至可以稱之爲一個錯誤。 –

回答

5

你不是真的碰到隱藏的C#功能,也許是一個模糊的實體框架功能。

當您分配CompanyId時,EF知道該公司有Id = 0(當時)是員工的父母。在許多場合,EF executes DetectChanges,其中還執行關係修復:匹配外鍵值和引用。出現這種情況,當你執行

context.Employees.Add(employee); 

現在EF將使用的參考,而不是外鍵值,所以它知道哪些FK值在數據庫中存儲。

當您創建兩個公司時,有兩個實例具有相同的臨時密鑰值,因此EF無法再選擇。

所以當你想存儲新的連接對象時,總是建議設置引用而不是FK值。

2

您已將公司添加到公司表。

context.Companies.Add(company); 

然後,設置員工的companyId:

CompanyId = company.Id 

這是所有需要創建SQL中的關係。實體框架可能插入了您的公司,然後插入帶有生成的最後一個身份的companyId的員工。

展望here我們可以看到,當存在重複的實體時,有問題使用ID。在你的情況下,兩家公司的ID都是0,直到它們被保存,所以實體框架不能唯一標識一家公司。

相關問題