2

我有一雙簡單的類在EF 4.1生成代碼第一次數據庫:EF代碼優先 - 多屬性指向另一個表

public class User 
{ 
    public int UserId { get; set; } 
    public string UserName { get; set; } 
} 

public class Purchase 
{ 
    public int PurchaseId { get; set; } 
    public int UserId { get; set; } 
    public int? SalespersonUserId { get; set; } 

    public User User { get; set; } 
    public User SalespersonUser { get; set; } 
} 

public class NewItemsDataContext : DbContext 
{ 
    public DbSet<User> Users { get; set; } 
    public DbSet<Purchase> Purchases { get; set; } 
} 

在我的計劃,我創建和一些數據寫入。

class Program 
{ 
    static void Main(string[] args) 
    { 
     Database.SetInitializer<NewItemsDataContext>(new DropCreateDatabaseIfModelChanges<NewItemsDataContext>()); 

     using (NewItemsDataContext sadc = new NewItemsDataContext()) 
     { 
      sadc.Users.Add(new User()); 

      sadc.SaveChanges(); 
     } 
     using (NewItemsDataContext sadc = new NewItemsDataContext()) 
     { 
      sadc.Purchases.Add(new Purchase() { UserId = 1 }); 
      sadc.SaveChanges(); 
     } 
     using (NewItemsDataContext sadc = new NewItemsDataContext()) 
     { 
      var sql = sadc.Purchases.Include(p => p.User); 
      foreach (Purchase purchase in sql) 
       Console.WriteLine(purchase.User.UserId.ToString()); 
     } 
    } 
} 

注意,當我讀到的購買記錄後,我得到purchase.User是空的例外 - 那就是,在.include沒有在用戶拉什麼。現在,如果我不理我OnModelCreating的salespersonUser導航屬性(或只是把它註釋掉):

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<Purchase>().Ignore(p => p.SalespersonUser); 

    base.OnModelCreating(modelBuilder); 
} 

代碼工作,並且用戶在在.include加載。

當SalespersonUser nav屬性被忽略時,創建的數據庫看起來就像您期望的那樣。 Purchase表具有PurchaseId,UserId和SalespersonId。但是,一旦將SalespersonUser nav屬性添加回(停止忽略它),您最終會在表中添加兩個鍵:User_UserId和SalespersonUser_UserId(以及原始UserId和SalespersonUserId)。

此外,生成的SQL明確顯示出現問題的位置。

沒有導航屬性:

{SELECT 
[Extent1].[PurchaseId] AS [PurchaseId], 
[Extent1].[UserId] AS [UserId], 
[Extent1].[SalespersonUserId] AS [SalespersonUserId], 
[Extent2].[UserId] AS [UserId1], 
[Extent2].[UserName] AS [UserName] 
FROM [Purchases] AS [Extent1] 
INNER JOIN [Users] AS [Extent2] ON [Extent1].[UserId] = [Extent2].[UserId]} 

,並與導航性能:

{SELECT 
[Extent1].[PurchaseId] AS [PurchaseId], 
[Extent1].[UserId] AS [UserId], 
[Extent1].[SalespersonUserId] AS [SalespersonUserId], 
[Extent2].[UserId] AS [UserId1], 
[Extent2].[UserName] AS [UserName], 
[Extent1].[SalespersonUser_UserId] AS [SalespersonUser_UserId] 
FROM [Purchases] AS [Extent1] 
LEFT OUTER JOIN [Users] AS [Extent2] ON [Extent1].[User_UserId] = [Extent2].[UserId]} 

注意它是如何拉的用戶ID,但與User_UserId聯接和左連接,不會少。 SalespersonUserId在連接中甚至沒有被引用。寫入記錄後在數據庫內部設置UserId,但User_UserID爲空。因此,沒有什麼可以加入,並且我們爲包含用戶得到空值。

在我看來,這是EF中的一個錯誤,但它可能有一個設計原因。如果是這樣,有人可以爲我清除它,也許可以描述一些可以解決它的流利的API?我對我的導航屬性有些偏愛。

+0

只是好奇:什麼是性能Purchase.UserId和Purchase.SalesPersonUserId的目的是什麼?這不是那種多餘的信息,因爲購買時還有可以找到Id的User和SalesPersonUser的引用?我之前沒有看到過這樣的設置... –

+1

這就是您如何使用EF Database First從數據庫中生成的類,這正是我正在做的。我有一個3層系統,在服務器端有一個數據庫,使用並提供從數據庫生成的類的Web服務,以及使用Web服務的WPF客戶端。 – user1689571

回答

2

EF有問題與您的導航屬性 - 這就是爲什麼它產生額外的FK的。

嘗試添加該流利的映射,所以找你明確地映射到FK NAV財產關係:

 modelBuilder.Entity<Purchase>() 
      .HasOptional(p => p.SalespersonUser) 
      .WithMany() 
      .HasForeignKey(p => p.SalespersonUserId); 

     modelBuilder.Entity<Purchase>() 
      .HasRequired(p => p.User) 
      .WithMany() 
      .HasForeignKey(p => p.UserId); 
+0

是的!我剛剛得到相同的代碼工作,當你的答案進來。很高興我想我終於明白了。謝謝! – user1689571

+0

「EF在您的導航屬性上遇到問題......」您會說這是一個錯誤嗎? – user1689571

+0

不是一個錯誤,而是來自發生器的混淆 - 它無法根據約定找出它,所以你只是想讓你清除它。 –