2

私のドメイン モデルには、Company抽象化された基本クラスと、Company のサブクラスによって表される 3 つの異なる Company タイプがあります。

public abstract class Company
{
    public int Id { get; set; }
    ...
}

public class Supplier : Company
{
    ...
}

public class Dealer : Company
{
    public DealerFundsAccount FundsAccount { get; set; }
    ...
}

public class Retailer : Company
{
    public RetailerFundsAccount FundsAccount { get; set; }
    ...
}

同様に、Funds Account を定義する別の基本クラスと、特定のプロパティを実装する 2 つのサブタイプがあります。

public abstract class FundsAccount
{
    public int Id { get; set; }
    ...
}

public class DealerFundsAccount : FundsAccount
{
    public Dealer Dealer { get; set; }
    ...
}

public class RetailerFundsAccount : FundsAccount
{
    public Retailer Retailer { get; set; }
    ...
}

これらの型に対する私のマッピング戦略は、階層ごとのテーブルであるため、私の DbContext クラスでは、基本クラスに対してのみ DbSet を定義します。これにより、ポリモーフィック クエリと非ポリモーフィック クエリの両方を実行できるようになります。

public DbSet<Company> Companies { get; set; }
public DbSet<FundsAccount> FundsAccounts { get; set; }

ここでトリッキーな部分が来ます。私の要件は次のように述べています。

  • サプライヤーは資金口座を持ってはなりません
  • ディーラーには DealerFundsAccount が必要です
  • 小売業者には RetailerFundsAccount が必要です

次のように単純なはずです。

modelBuilder.Entity<Retailer>()
    .HasRequired(r => r.FundsAccount)
    .WithRequiredDependent(rfa => rfa.Retailer);

modelBuilder.Entity<Dealer>()
    .HasRequired(d => d.FundsAccount)
    .WithRequiredDependent(dfa => dfa.Retailer);

しかし、EF Migrations はデータベース スキーマを更新しようとして惨めに失敗します。TPH により、Dealers と Retailers は同じ Company データベース テーブルにマップされ、RetailerFundsAccounts と DealerFundsAccounts は FundsAccount db テーブルにマップされます。これはすべて望ましいことですが、サブタイプ間に 2 つの 1 対 1 の関係を定義したため、EFはFundsAccount Id フィールドに外部キーを 2 回定義します

資金口座を持つ Company テーブルごとに 1 対多の関係を定義し、FK の一意の制約を使用して 1 対多の動作を防止することで、ソリューションをハックできることはわかっていますが、より良い解決策があります。

4

1 に答える 1

0

EF の移行が原因であることがわかりました。データベース スキーマを最初から作成しようとすると、すべて問題ありませんが、移行を作成してこれらのエンティティを追加すると、EF は次のようにインデックスと外部キーを 2 回作成しようとして失敗します。

        CreateTable(
            "dbo.FundsAccount",
            c => new
                {
                    Id = c.Int(nullable: false),
                    Discriminator = c.String(nullable: false, maxLength: 128),
                })
            .PrimaryKey(t => t.Id)
            .ForeignKey("dbo.Company", t => t.Id)
            .ForeignKey("dbo.Company", t => t.Id) // duplicate
            .Index(t => t.Id)
            .Index(t => t.Id); // duplicate

解決策は、移行を編集して、重複する FK およびインデックス エントリを削除することです。

問題をより適切に説明するために、質問のタイトルも更新します。

于 2013-10-28T13:36:36.233 に答える