2011-11-07 32 views
1

我正在嘗試定義與供應商,經銷商和零售商的供應鏈。這些實體受合同類的約束,該類還定義了ProductLine和他們將使用的產品。 對於給定的ProductLine,供應商(該ProductLine的唯一所有者)和經銷商之間會有合同,然後是該經銷商和零售商之間的另一個合同。EF 4.1上的接口和多重約束衝突代碼優先

問題是兩個經銷商之間也有合同,所以我嘗試創建兩個接口(ISeller和IBuyer)。供應商實現ISeller,零售商實現IBuyer和經銷商實現兩個接口:

public class Supplier : ISeller 
{ 
    public int Id { get; set; } 
    public virtual ICollection<Contract> Contracts { get; set; } 
} 

public class Dealer : ISeller, IBuyer 
{ 
    public int Id { get; set; } 
    public virtual ICollection<Contract> Contracts { get; set; } 
} 

public class Retailer : IBuyer 
{ 
    public int Id { get; set; } 
    public virtual ICollection<Contract> Contracts { get; set; } 
} 

然後將合同界定出ISeller到IBuyer,像這樣:

public class Contract 
{ 
    public int Id { get; set; } 
    public virtual ISeller Seller { get; set; } 
    public virtual IBuyer Buyer { get; set; } 
} 

創建供應商/經銷商或經銷商/零售商之間的合同按預期工作,但在嘗試創建經銷商/經銷商合同時,我得到'多重約束違反'。

+0

你可以看看從你的類設計中生成的數據庫模式嗎?這可能會揭示爲什麼這種關係有問題。 –

+0

是的,我忘記提到合約表的佈局有點奇怪: Id | Supplier_Id | Dealer_Id |零售商_Id 這種方式很明顯,我不能在同一合同中擁有兩個經銷商。也許我應該使用自定義映射來幫助EF瞭解我正在嘗試做什麼。問題是我對Fluent API不太熟練。 :) –

+0

那麼,那是你的問題。儘管如此,我還不太瞭解EF Code First,所以這是我個人可以提供的所有幫助。 –

回答

6

看來,這段代碼的問題是接口。正如Slauma在評論中所說的那樣,Contract類的接口成員根本不會被映射,因爲EF不知道哪些實體 - 供應商,代理商或兩者 - 映射到賣方成員。

從另一個方面來看,我們認爲每個供應鏈參與者都有多個合同。這將導致Contracts表中的Supplier_id,Dealer_id,Reseller_id列。從EF的角度來看,供應商和經銷商沒有共同之處,零售商和經銷商也沒有共同之處。

你需要做的是有實體繼承。經銷商既可以是賣方也可以是買方,所以你不能擁有2個獨立的類,因爲C#不允許多重繼承。定義ContractParticipant基礎實體並讓供應商,代理商和零售商從中繼承。那麼你的數據模型看起來是這樣的:

public abstract class ContractParticipant 
{ 
    public int Id { get; set; } 
    [InverseProperty("Seller")] 
    public virtual ICollection<Contract> SellerContracts { get; set; } 
    [InverseProperty("Buyer")] 
    public virtual ICollection<Contract> BuyerContracts { get; set; } 
} 

public class Supplier : ContractParticipant 
{ 
    <...other properties here...> 
} 

public class Dealer : ContractParticipant 
{ 
    <...other properties here...> 
} 

public class Retailer : ContractParticipant 
{ 
    <...other properties here...> 
} 

public class Contract 
{ 
    public int Id { get; set; } 
    public virtual ContractParticipant Seller { get; set; } 
    public virtual ContractParticipant Buyer { get; set; } 
} 

這種模式應該產生一個能夠支持您的方案,沒有任何其他的配置數據庫結構。然而,它也允許任何類型的參與者之間的合同,但如果你試圖在數據模型中映射多重繼承,你最終會得到類似於this的東西 - 考慮是否想使數據模型複雜化以保留這些約束。

+0

+1:這看起來不錯! (一點:我認爲你的意思是'[InverseProperty(...)]'屬性,而不是'[ForeignKey(...)]'。) – Slauma

+0

謝謝。更正:) –

+0

非常感謝!看起來我們在這裏有一個贏家。我可以使用自定義實體驗證來抑制供應商/供應商與零售商/零售商之間簽訂的合同,因此這不成問題。 –

0

嘗試使用這一個:

public class Contract 
{ 
    public int Id { get; set; } 
    public virtual Seller Sellers { get; set; } 
    public virtual Buyer Buyers { get; set; } 
}