How to associate one table to many parents using E

2019-05-16 12:35发布

问题:

I am building a domain model that requires several tables to be able to be references by more than one possible parent table. Something like you might have a table to store notes or files and those notes and/or files can be associated with different parent entities. Not that the same "file" or "note" can be associate with multiple owners, but that of 10 rows in a "files" table, 3 of them might be owned by rows from a "Customer" table, 3 of them might be owned by rows from an "Orders" table, and 4 of them might be owned by rows from a "Person" table.

The owning tables all have virtual ICollections of the child tables.

When I ran my model through the code first migration for the initial migration, and looked at the generated fluent code, the table definition for these tables included multiple id columns that referred back to the source table, so that there would be a column "customer_id," "person_id," etc. (one for each possible "owning entity." This doesn't seem quite "right." Is there a better way to model this in EF with CodeFirst? Like being able to use a discriminator column in the child table that provides a "hint" about the owning entity?

Thanks, -MrB

回答1:

If you create a many-to-many relationship between notes and all entities that can have notes, you will have a junction table for each owning type and a nice and clean note table. The simplest way to create the many-to-many relationships is to override the DbContext.OnModelCreating method.

Your DbContext:

  public class MyDatabase : DbContext
  {
    // Protected methods

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
      base.OnModelCreating(modelBuilder);

      modelBuilder.Entity<Customer>().HasMany(x => x.Notes).WithMany();
      modelBuilder.Entity<Order>().HasMany(x => x.Notes).WithMany();
    }

    public MyDatabase() : base("MyDatabase")
    {
    }

    // Properties

    public DbSet<Customer> Customers { get; set; }

    public DbSet<Order> Orders { get; set; }

    public DbSet<Note> Notes { get; set; }
  }

This will produce the following tables: Customer, Orders, Notes, CustomerNotes and OrderNotes with the last two being junction tables with only two columns each.

NOTE! With this solution it is also possible for entities to share notes, e.g. a Customer and an Order can own the same Note.



回答2:

Not sure if fits but you could use EF hierarchies to do it. See This article:

http://weblogs.asp.net/manavi/archive/2010/12/24/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1-table-per-hierarchy-tph.aspx

Basically you could have three types for your notes all inheriting from a basic note type.

There are three types of hierarchies in EF so its a three partes article...