简体   繁体   中英

EF6 Many to Many relationship, multiple tables to join table

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.

表关系图

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM