EF6 Many to Many relationship, multiple tables to join table

c# entity-framework-6

Question

Apologies for the long title, couldn't think of a better way to sum this problem up.

I'm trying to rewrite an existing L2S context using EF6 and there is an admittedly questionable relationship that it is having trouble with.

diagram of table relationships

EntityAttributes acts as a join table for many tables, including Materials and Formulas, to Attributes.

All of the tables on the left hand side have an Id Identity column and an EntityTypeId column as a composite PK. The value of the EntityTypeId column is unique to each table (Materials is 1, Formulas is 2, etc)

The Attributes table has a composite PK of Id (Identity) and EntityTypeId.

The EntityAttributes table has a PK of Id (Identity) and AttributeId and EntityTypeId as FK on to Attributes.

When attempting to create an EntityAttribute, I get the following exception:

A dependent property in a ReferentialConstraint is mapped to a store-generated column. Column: 'Id'.

The root problem I believe is that Materials, Formulas, etc relationship on to EntityAttributes is unenforceable at the database level. L2S didn't seem to mind this but EF6 seems to be much truer to the underlying data store's restrictions.

So my question is two-fold: 1. Is there a way to make EF work with this relationship as it is currently set up? 2. If not, what is a better design to achieve the same result? I have full control of the database schema.

Material class:

public partial class Material
{
    [Key]
    [Column(Order = 0)]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Key]
    [Column(Order = 1)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int EntityTypeId { get; set; }
}

EntityAttribute class:

public partial class EntityAttribute
{
    [Key]
    [Column(Order = 0)]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Key]
    [Column(Order = 1)]
    public int AttributeId { get; set; }

    [Key]
    [Column(Order = 2)]
    public int EntityId { get; set; }

    [Key]
    [Column(Order = 3)]
    public int EntityTypeId { get; set; }
}

Attribute class:

public partial class Attribute
{
    [Key]
    [Column(Order = 0)]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Key]
    [Column(Order = 1)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int EntityTypeId { get; set; }
}

Relationship definition in OnModelCreating:

    modelBuilder.Entity<Attribute>()
      .HasMany(e => e.EntityAttributes)
      .WithRequired(e => e.Attribute)
      .HasForeignKey(e => new { e.AttributeId, e.EntityTypeId });

I've tried every combination of changing the attributes and different relationship set ups in OnModelCreating, I've been spinning my wheels on this for 3 days now and can no longer see the wood for the trees.

1
0
7/31/2018 8:18:35 PM

Accepted Answer

What you want is Table per Hierarchy where your table for EntityAttribute will have discriminator field to determine your entity is either Material or Formula.

public class EntityAttribute
{
    public int Id { get; set; }
    public int AttributeId { get; set; }
    public int EntityId { get; set; }
    ...
}

public class Material : EntityAttribute
{
    public int Id { get; set; }
    ...
}

public class Formula : EntityAttribute
{
    public int Id { get; set; }
    ...
}

Following links to help: learn entity framework TPH and inheritance mapping strategies with entity framework code first

1
8/1/2018 7:21:14 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow