30

Entity Framework Code Firstアプローチ を使用して次のテーブルを作成しました。

  1. 不要な Discriminator 列がデータベースに作成されないように C# コードを変更するにはどうすればよいですか? これを達成するための属性はありますか?
  2. PaymentIDの代わりに名前を付けた外部キー列を作成するにはどうすればよいPayment_ PaymentIDですか? これを達成するための属性はありますか?

注: EntityFramework.dll のランタイム バージョンはv4.0.30XXXです。

ここに画像の説明を入力

コード

public abstract class PaymentComponent
{
    public int PaymentComponentID { get; set; }
    public int MyValue { get; set; }
    public string MyType { get; set; }
    public abstract int GetEffectiveValue();
}

public partial class GiftCouponPayment : PaymentComponent
{
    public override int GetEffectiveValue()
    {
        if (MyValue < 2000)
        {
            return 0;
        }
        return MyValue;
    }
}

public partial class ClubCardPayment : PaymentComponent
{
    public override int GetEffectiveValue()
    {
        return MyValue;
    }
}

public partial class Payment
{
    public int PaymentID { get; set; }
    public List<PaymentComponent> PaymentComponents { get; set; }
    public DateTime PayedTime { get; set; }
}

//System.Data.Entity.DbContext is from EntityFramework.dll
public class NerdDinners : System.Data.Entity.DbContext
{
    public NerdDinners(string connString) : base(connString)
    { 

    }

    protected override void OnModelCreating(DbModelBuilder modelbuilder)
    {
        modelbuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }

    public DbSet<GiftCouponPayment> GiftCouponPayments { get; set; }
    public DbSet<ClubCardPayment> ClubCardPayments { get; set; }
    public DbSet<Payment> Payments { get; set; }
}

クライアント

static void Main(string[] args)
{
    string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30";

    using (var db = new NerdDinners(connectionstring))
    {                
        GiftCouponPayment giftCouponPayment = new GiftCouponPayment();
        giftCouponPayment.MyValue = 250;
        giftCouponPayment.MyType = "GiftCouponPayment";

        ClubCardPayment clubCardPayment = new ClubCardPayment();
        clubCardPayment.MyValue = 5000;
        clubCardPayment.MyType = "ClubCardPayment";

        List<PaymentComponent> comps = new List<PaymentComponent>();
        comps.Add(giftCouponPayment);
        comps.Add(clubCardPayment);

        var payment = new Payment { PaymentComponents = comps, PayedTime=DateTime.Now };
        db.Payments.Add(payment);

        int recordsAffected = db.SaveChanges();
    }
}
4

7 に答える 7

34

TPH 継承には、エンティティのタイプを識別するために使用される特別な列が必要です。デフォルトでは、この列が呼び出されDiscriminator、派生エンティティの名前が含まれます。Fluent-API を使用して、異なる列名と異なる値を定義できます。MyType 列は実際には識別子であるため、直接使用することもできますが、そのような場合、エンティティにその列を含めることはできません (列は 1 回だけマップでき、識別子として使用する場合は既にマッピングと見なされます)。

外部キー列の名前は、Fluent-API で再び制御できます。

protected override void OnModelCreating(DbModelBuilder modelbuilder)
{
    modelbuilder.Conventions.Remove<PluralizingTableNameConvention>();

    // Example of controlling TPH iheritance:
    modelBuilder.Entity<PaymentComponent>()
            .Map<GiftPaymentComponent>(m => m.Requires("MyType").HasValue("G"))
            .Map<ClubPaymentComponent>(m => m.Requires("MyType").HasValue("C"));

    // Example of controlling Foreign key:
    modelBuilder.Entity<Payment>()
                .HasMany(p => p.PaymentComponents)
                .WithRequired()
                .Map(m => m.MapKey("PaymentId"));
}
于 2012-07-24T12:58:32.820 に答える
3

Table per Type (TPT) も使用できます。

http://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-2-table-per-type-tpt

タイプごとのテーブル (TPT)

Type per Type は、継承関係をリレーショナル外部キー アソシエーションとして表すことに関するものです。永続プロパティを宣言するすべてのクラス/サブクラス (抽象クラスを含む) には、独自のテーブルがあります。サブクラスのテーブルには、基本クラス テーブルの外部キーでもある主キーと共に、継承されていない各プロパティ (サブクラス自体によって宣言された各プロパティ) の列のみが含まれます。

EF Code First で TPT を実装する

サブクラスに Table 属性を配置してマップされたテーブル名を指定するだけで、TPT マッピングを作成できます (Table 属性は新しいデータ注釈であり、CTP5 の System.ComponentModel.DataAnnotations 名前空間に追加されました。

流暢な API を好む場合は、ToTable() メソッドを使用して TPT マッピングを作成できます。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<BankAccount>().ToTable("BankAccounts");
    modelBuilder.Entity<CreditCard>().ToTable("CreditCards");
}
于 2014-12-29T16:26:30.537 に答える
1

サブクラスを使用しているため、サブクラスの各タイプを区別するために Discriminator 列が必要です。

于 2012-07-24T12:13:55.637 に答える
0

"GiftCouponPayment" と "ClubCardPayment" の両方が "PaymentComponent" から派生するため、EF は個別のテーブルを使用せず、その列が必要になります。別の動作が必要な場合は、デフォルトのテーブル アクセスをオーバーライドし、フィールドをクラスにマップする必要があります (これはやりたくないと思います)。これに簡単な方法があるかどうかはわかりません。まずエンティティから、テーブルを作成するテンプレートを使用する方法があることを知っています。
外部キー列名についても同様です。EF は、キー/外部キー名の名前を作成する方法を使用します。テーブルを好きなようにフォーマットしたい場合は、すべて自分で行う必要があります。これにより、なぜEFを使用するのかという疑問が生じます。
化粧品以外に、それをやりたい特別な理由はありますか?

于 2012-07-24T12:17:28.167 に答える