EntityFrameworkコアでの継承のマッピング

design-patterns ef-fluent-api entity-framework entity-framework-core orm

質問

私はEntityFramework Core、Code First、Fluent Apiを使用してモデルデータベースを定義しています。マップ継承の戦略については、

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; }
}

ビジネス論理

この場合、ユーザー、従業員および顧客は人ですが、従業員と顧客もユーザーであり、従業員は顧客になることができます。また、それぞれのタイプは異なるアプリケーションのコンテキストで使用されます。

私は、他のアプリケーションコンテキストからの値を不必要に使用しないようにこの方法を実装しました。

質問:

  1. データベースモデルをマップするベストプラクティスは何ですか?タイプごとのHyerarchyまたはテーブルごとのタイプ?多くの人にとって、 TPTは一般的に反パターンであり、後で重大なパフォーマンス上の問題を引き起こすことに注意してください。 EF問題#2266に従って

    a。 TPHの場合、discriminatorフィールドをどのように使用するのですか?

    b。 TPTの場合は、EF Core 1.0でこの戦略をどのように使用するのですか?

  2. それはビジネスモデルにとって最高のアーキテクチャですか?

ご協力いただきありがとうございます

人気のある回答

私はEFコアで遊んだり、EF6に慣れたりして、タイプごとのテーブルを広範囲に使用していたとき、これを簡単に調べました。

1a)私の経験では、各エンティティタイプをDbSetとしてコンテキストに追加するだけで、デフォルトのマッピングが非常にうまくいくということです。必要に応じて、DbContextのOnModelBuildingオーバーライドでこれを設定できます。

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

1b)現在、EFコアでTPTを使用することはできません。これは将来のリリース用に計画されており、現在EFコアロードマップに「高優先度」としてリストされています

2)厳密なDDD原則を採用している場合、ビジネスレイヤーは実際のドメインを可能な限り密接にモデル化/ミラー化し、アプリケーションのデータレイヤの影響を受けないようにする必要があります。個人的には、あなたが上に示したような継承は、現実の状況の良い鏡だと思います。しかし、EFのコアチームは、「継承を超えた構成」のキャンプにいるようで、次のようなドメインモデルにつながる可能性があります。

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; }
}

次に、これらのエンティティは別々のテーブルに格納され、それらの間には事前キーの関係があります。従業員の顧客への移行にも、従業員と同じユーザー属性を持つ新しい顧客の作成が必要になります。

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();
}


Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ