Mapping inheritance in EntityFramework Core

孤者浪人 提交于 2021-01-27 21:10:22

问题


I'm using EntityFramework Core, Code First and Fluent Api to define model database, and i've follow situation about strategy of map inheritance:

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

public class User : Person
{
    public string UserName { get; set; }
    public string Password { get; set; }
}

public class Employee : Person
{
    public decimal Salary { get; set; }
}

public class Customer:Person
{
    public long DiscountPoints { get; set; }
}

Business logical

In this case, users, employees and customers are people, however employees and customers are also users, as well as an employees can become a customer. And each type is used in distinct appication contexts.

I implemented this way to not use values from other application contexts unnecessarily.

Questions:

  1. What are the best practice to map a database model? Type-Per-Hyerarchy or Table-Per-Type? Considering that for many, TPT is generally an anti-pattern and results in significant performance issues later on. according EF issues #2266

    a. If TPH, how to use discriminator field to many types?

    b. If TPT, how to use this strategy in the EF Core 1.0?

  2. Is it the best architecture for the business model?

thank you for your attention and collaboration


回答1:


I looked into this briefly when playing with EF core, having been used to EF6, and extensively used table-per-type.

1a) My experience is that the default mappings do quite well if you just add each entity type as a DbSet to your context. If necessary then you can configure this in the OnModelBuilding override in your DbContext:

protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Person>()
            .HasDiscriminator<string>("person_type")
            .HasValue<Employee>("employee")
            .HasValue<Customer>("customer");
    }

1b) At present you can't use TPT with EF core. It is planned for future releases and is currently listed as High Priority on the EF core roadmap

2) If we are employing strict DDD principles then the business layer should model/mirror the real-life domain as closely as possible and not be influenced by the data layer of an application. Personally I think that inheritance as you have laid out above is a good mirror of a real-life situation. However, the EF core team seem to be in the "favour composition over inheritance" camp, which might lead to domain models such as:

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

public class User
{
  public int Id {get;set;}
  public Person Person {get; set;}
  public int PersonId {get;set;}
  public string UserName { get; set; }
  public string Password { get; set; }
}

public class Employee
{
  public int Id {get; set;}
  public User User {get; set;}
  public int UserId {get;set;}
  public decimal Salary { get; set; }
}

public class Customer
{
  public int Id {get;set;}
  public User User {get; set;}
  public int UserId {get;set;}
  public long DiscountPoints { get; set; }
}

These entitites would then be stored in separate tables, with foreigh-key relationships between them. The transition of an employee to being a customer as well, would involve creating a new customer, with the same user property as the employee, e.g.

public void CreateCustomerFromEmployee(int employeeId) {
  var employee = context.Employees.Where(e => e.Id == employeeId).SingleOrDefault();

  context.Customers.Add(new Customer() 
    {
        UserId = employee.UserId,
        DiscountPoints = 0
    });

  context.SaveChanges();
}


来源:https://stackoverflow.com/questions/40154440/mapping-inheritance-in-entityframework-core

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!