使用现有基类实例的Entity Framework继承

时间:2014-07-29 13:02:42

标签: c# entity-framework ef-code-first table-per-type

我在我的模型中使用TPT策略。

以下是我的背景:

public class MyTestContext : DbContext
{
    public DbSet<Person> Persons { get; set; }
    public DbSet<Seller> Sellers { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        modelBuilder.Entity<Person>().ToTable("Persons");
        modelBuilder.Entity<Seller>().ToTable("Sellers");
        base.OnModelCreating(modelBuilder);
    }
}

这是我的实体:

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Seller : Person
{
    public decimal Comissao { get; set; }
}

我正在尝试重用已存在的数据库寄存器。 我有2个CRUD,一个用于Person,另一个用于卖方。

情景:

我的数据库中有10个人,0个卖家,就像这个种子:

using (var ctx = new MyTestContext())
{
    Func<int, Person> selector = i => new Person
    {
        Name = string.Format("Person {0}", i)
    };
    var persons = Enumerable.Range(1, 10).Select(selector);
    ctx.Persons.AddRange(persons);

    ctx.SaveChanges();
}

我想添加新的卖家,但我想在数据库中重用alredy现有的Person:

using (var ctx = new MyTestContext())
{
    var seller = new Seller { Id = 1, Comissao = 10 };
    ctx.Sellers.Add(seller);

    ctx.SaveChanges();
}

当Entity Framework保存时,他会创建一个新的Person和一个新的Seller。

如何使用继承策略并能够使用我在Seller中指定的ID来创建新Person并使用这个新Id?

1 个答案:

答案 0 :(得分:0)

您无法将TPT用于一对一或零关系。

因为能够拥有一对一或零关系。您需要Seller上的PersonPerson属性Seller属性。

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Seller Seller { get; set; }
}
public class Seller : Person
{
    public decimal Comissao { get; set; }
    public Person Person { get; set; }
}

但是上面的代码不起作用,因为Person上的Seller属性也将继承到Seller,它将被视为另一种关系。

解决方案

  • 有另一个名为BasePerson
  • 的抽象类
  • PersonSeller都来自BasePerson
  • 使用表格每具体类映射

以下是课程

public abstract class BasePerson
{
    public int Id { get; set; }
    public string Name { get; set; }
}
public class Person : BasePerson
{
    public Seller Seller { get; set; }
}
public class Seller : BasePerson
{
    public decimal Comissao { get; set; }
    public Person Person { get; set; }
}    
public class AppContext : DbContext
{
    public DbSet<Person> People { get; set; }
    public DbSet<Seller> Sellers { get; set; }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // Configures one to one-or-zero relationship.
        modelBuilder.Entity<Seller>().HasRequired(x => x.Person).WithRequiredDependent(x => x.Seller);
    }
}

样本用法

using (var context = new AppContext())
{
    context.People.Add(new Person { Id = 1 });
    context.SaveChanges();
}
using (var context = new AppContext())
{
    context.Sellers.Add(new Seller { Id = 1 });
    context.SaveChanges();
}
using (var context = new AppContext())
{
    // Throws DBUpdateException, Person Id = 2 doesn't exist.
    context.Sellers.Add(new Seller { Id = 2 });
    context.SaveChanges();
}