How can I use TPT inheritance models when primary

2019-02-11 05:01发布

问题:

Using Entity Framework 4.1 against a legacy database, I'm unable to generate a working set of TPT inheritance models that aren't pluralized and use different names for a common primary key.

I am using database tables Organization, Account, and Company as illustrated below:

Organization
  OrganizationID (int PK)
  OrgName (varchar)

Company
  CompanyID (int PK)
  CompanyNo (varchar)

Account
  AccountID (int PK)
  AccountNo (varchar)

Account.AccountID and Company.CompanyID have a FK constraint that values in those columns must also be contained in Organization.OrganizationID so neither can exist without a Organization row. If I were designing these tables from scratch, both Account and Company would use OrganizationID as their primary key instead.

public partial class BusinessEntities : DbContext
{
    public BusinessEntities()
        : base("name=BusinessEntities")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Organization>().ToTable("Organization");

        // Override pluralization
        modelBuilder.Entity<Company>().ToTable("Company");
        modelBuilder.Entity<Account>().ToTable("Account");

        // Set primary key column for each
        modelBuilder.Entity<Company>().Property(
            e => e.OrganizationID).HasColumnName("CompanyID");
        modelBuilder.Entity<Account>().Property(
            e => e.OrganizationID).HasColumnName("AccountID");
    }

    public DbSet<Organization> Organization { get; set; }
}

public partial class Organization
{
    public int OrganizationID { get; set; }
    public string OrgName { get; set; }
}

public partial class Account : Organization
{
    public string AccountNo { get; set; }
}

public partial class Company : Organization
{
    public string CompanyNo { get; set; }
}

When I try to use the simple select code listed below, I receive the error:

The property 'OrganizationID' is not a declared property on type 'Company'. Verify that the property has not been explicitly excluded from the model by using the Ignore method or NotMappedAttribute data annotation. Make sure that it is a valid primitive property.

static void Main(string[] args)
{
    using (var context = new BusinessEntities())
    {
        foreach (var b in context.Organization.OfType<Company>())
        {
            Console.WriteLine("{0} {1}", b.CompanyNo, b.OrgName);
        }

        foreach (var b in context.Organization.OfType<Account>())
        {
            Console.WriteLine("{0} {1}", b.AccountNo, b.OrgName);
        }
    }
    Console.ReadLine();
}

回答1:

I described TPT mapping here. It is step by step so it should work but you need to map Ids in child entities.

But the issue is that you start with Model-first, generate DdContext which is dependent on EDMX, then delete that EDMX and start defining mapping by yourselves. You should decide if you want to use Model-first or Code-first. You just wasted your effort in EDMX.

If you want to know how to use Model-first with DbContext check this article. If you want to use Code-first don't create EDMX and follow this article to map your inheritance.