2011-09-21 103 views
3

我正在EF 4.1的第一步。因爲我使用的是NHibenate,所以在我看來,代碼優先的方法是最好的。我對於一對多(或多對一)真實性的良好映射存在問題。假設我有兩個實體:實體框架一對多關係代碼

class ClientModel 
{ 
    int ClientID; 
    string Name; 
    virtual IList<OrderModel> Orders; 
} 

class OrderModel 
{ 
    int OrderID; 
    string Details; 
    virtual ClienModel Client; 
} 

當我這樣離開時,生成數據庫時出現錯誤 - 表中的鍵缺失。我想通過將密鑰的名稱更改爲ID(但它不符合我的命名約定)或通過添加[Key]註釋來修復它。即使我添加了這個註解,表名仍然是錯誤的 - 就像類的名字,但是用's'。 所以我試圖使用流利的API - 我做了映射。但是,如果我設置的映射就像這樣:

class ClientMapping 
{ 
    ClientMapping() 
    { 
     this.HasKey(e => e.ClientID).Property(e => e.ID).HasColumnName("ClientID"); 
     this.Property(e => e.Name).HasColumnName("Name"); 
     this.HasMany(e => e.Orders).WithOptional().Map(p => p.MapKey("OrderID")).WillCascadeOnDelete(); 
     this.ToTable("Clients"); 
    } 
} 

class OrderMapping 
{ 
    OrderMapping() 
    { 
     this.HasKey(e => e.OrderID).Property(e => e.OrderID).HasColumnName("OrderID"); 
     this.Property(e => e.Details).HasColumnName("Details"); 
     this.HasRequired(e => e.Client).WithMany().Map(p=>p.MapKey("Client")).WillCascadeOnDelete(false); 
     this.ToTable("Orders"); 
    } 
} 

數據庫中表之間的關係增加了一倍。 使用代碼優先方法進行一對多關係的正確方法是什麼?我是朝着一個好的方向思考還是錯誤的方法?

編輯

OK,我已經在路上@Eranga表現做了,但仍是一個問題。當我從數據庫獲取客戶端時,其Orders屬性爲空(但在數據庫中它有一些Order.ClientID == Client.ClientID的訂單)。

+0

我測試了我的答案給出的配置和正常工作。確保'訂單'是一個財產,而不是一個領域。 – Eranga

+0

嘗試'虛擬列表訂單;'而不是'虛擬IList 訂單;' –

回答

6

您需要映射參與關係的兩個屬性。您需要將ClientID列添加到訂單表。

class ClientMapping 
{ 
    ClientMapping() 
    { 
     this.HasKey(e => e.ClientID).Property(e => e.ID).HasColumnName("ClientID"); 
     this.Property(e => e.Name).HasColumnName("Name"); 

     this.HasMany(e => e.Orders).WithRequired(o => o.Client) 
      .Map(p => p.MapKey("ClientID")).WillCascadeOnDelete(); 

     this.ToTable("Clients"); 
    } 
} 

class OrderMapping 
{ 
    OrderMapping() 
    { 
     this.HasKey(e => e.OrderID).Property(e => e.OrderID).HasColumnName("OrderID"); 
     this.Property(e => e.Details).HasColumnName("Details"); 
     this.ToTable("Orders"); 
    } 
} 

從一個實體配置關係就足夠了。

+1

「您需要映射兩個參與關係的屬性,您需要將ClientID列添加到訂單表。 你到底意味着什麼? – rideronthestorm

+0

@rideronthestorm'ClientModel'中的Orders'屬性和'OrderModel'中的'Client'屬性作爲關係的兩個參與者。 – Eranga

+1

我還是不明白。我不是在映射他們兩個嗎?也許你可以發佈完整的代碼? 爲什麼我需要OrderID(OrderModel?)中的ClientID? – rideronthestorm

0

這可能有助於(它幫助我,當我無法弄清楚如何工作):

如果你將有類是這樣的:

class ClientModel 
{ 
    int ClientId; 
    string Name; 
} 

class OrderModel 
{ 
    int OrderId; 
    string Details; 
    int ClientId; 
} 

那麼這將是2個表在你的數據庫中「不會」通過外鍵相互連接(它們將通過OrderModel中的ClientId連接),並且可以從數據庫中獲得諸如「GetAllOrdersWithSomeClientId」和「GetTheClientNameForSomeClientId」之類的數據。但是,當你從數據庫中刪除Client時會出現問題。因爲那樣仍然會有一些Orders,其中將包含ClientId,該表不存在於Client表中,並且會導致數據庫中出現異常。

需要virtual List<OrderModel> Orders;(在ClientModel)和virtual ClienModel Client;(在OrderModel)來創建關係aka。表ClientModelOrderModel之間的外鍵。

有一件事我仍然不確定。這是OrderModel中的int ClientId;。我想它必須與ClientModel中的ClientId具有相同的名稱,以便實體框架知道外鍵必須連接哪兩個屬性。如果有人能夠詳細解釋這一點會很好。

而且,要把它放到你的DbContext的構造函數,如果事情souldn't工作:

this.Configuration.ProxyCreationEnabled = false; 
this.Configuration.LazyLoadingEnabled = false;