Henrique Miranda
Henrique Miranda

Reputation: 1108

Interfaces and multiplicity contraint violation on EF 4.1 Code-first

I'm trying to define a supply chain with Suppliers, Dealers and Retailers. This entities are bound by a Contract class that also defines the ProductLine and the Products they will work with. For a given ProductLine, there will be a contract between a Supplier (the sole owner of that ProductLine) and a Dealer, and then another contract between this Dealer and a Retailer.

The problem is that there's also a contract between two dealers so I tried creating two interfaces (ISeller and IBuyer). Supplier implements ISeller, Retailer implements IBuyer and Dealer implements both interfaces:

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; }
}

The Contract then bounds a ISeller to a IBuyer, like this:

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

Creating contracts between Supplier/Dealer or Dealer/Retailer works as intended, but I get a 'Multiplicity constraint violated' when trying to create a Dealer/Dealer contract.

Upvotes: 1

Views: 370

Answers (2)

Vytautas Mackonis
Vytautas Mackonis

Reputation: 462

It seems that the problem with this code is the interfaces. As Slauma said in the comments, the interface members of Contract class are not mapped at all since EF does not know, for example, which entities - Supplier, Dealer or both - map to Seller member.

From the other direction we have that each of the supply chain participants have multiple contracts. This results in Supplier_id, Dealer_id, Reseller_id columns in Contracts table. From EF perspective, Supplier and Dealer have nothing in common, neither do Retailer and Dealer.

What you need to do is to have entity inheritance. Dealer can be both seller and buyer though so you cannot have 2 separate classes as C# does not allow multiple inheritance. Define ContractParticipant base entity and have Supplier, Dealer and Retailer inherit from it. Then your data model would look something like:

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 model should generate database structure that would support your scenario without any other configuration. However it would also allow contracts between any types of participants but If you try to map multiple inheritance in data model you would end up with something like this - consider if you want to complicate your data model to preserve these constraints.

Upvotes: 6

Pankaj Upadhyay
Pankaj Upadhyay

Reputation: 13574

Trying using this one :

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

Upvotes: 0

Related Questions