webentwicklung-frage-antwort-db.com.de

Entity Framework: Wie vermeide ich die Diskriminator-Spalte aus der Tabelle?

Ich habe die folgende Tabelle mit Entity Framework Code First erstellt. 

  1. Wie ändere ich den C # -Code so, dass die unerwünschte Discriminator-Spalte nicht in der Datenbank erstellt wird? Gibt es irgendwelche Attribute, um das zu erreichen?
  2. Wie wird der Name der Fremdschlüsselspalte als "PaymentID" anstelle von "Payment_ PaymentID" festgelegt? Gibt es irgendwelche Attribute, um das zu erreichen?

Hinweis: Die Laufzeitversion für EntityFramework.dll lautet v4.0.30XXX

enter image description here

CODE

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

}

KLIENT

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


        }

    }
26
Lijo

Für die TPH-Vererbung ist eine spezielle Spalte erforderlich, mit der der Entitätstyp identifiziert wird. Standardmäßig heißt diese Spalte Discriminator und enthält Namen abgeleiteter Entitäten. Sie können die Fluent-API verwenden, um verschiedene Spaltennamen und unterschiedliche Werte zu definieren. Sie können Ihre MyType-Spalte auch direkt verwenden, da es sich tatsächlich um einen Diskriminator handelt. In diesem Fall können Sie diese Spalte jedoch nicht in Ihrer Entität haben (die Spalte kann nur einmal zugeordnet werden. Wenn Sie sie als Diskriminator verwenden, wird sie bereits als Zuordnung betrachtet).

Der Name der Fremdschlüsselspalte kann erneut mit der Fluent-API gesteuert werden:

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"));
}
30
Ladislav Mrnka

Fügen Sie das Attribut [NotMapped] hinzu, wenn die Eigenschaft der Spalte nicht zugeordnet wird.

8
John Li

Könnte auch Tabelle pro Typ (TPT) verwenden.

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

Tabelle pro Typ (TPT)

In Tabelle pro Typ werden Vererbungsbeziehungen als .__ dargestellt. relationale Fremdschlüsselverbände. Jede Klasse/Unterklasse, die deklariert persistente Eigenschaften - einschließlich abstrakter Klassen - ihre eigenen Tabelle. Die Tabelle für Unterklassen enthält nur Spalten für jedes nicht übernommene Eigenschaft (jede Eigenschaft wird von der Unterklasse selbst deklariert) zusammen mit einem Primärschlüssel, der auch ein Fremdschlüssel der Basisklasse ist Tabelle.

Implementieren Sie TPT zuerst in EF-Code

Wir können ein TPT-Mapping erstellen, indem Sie einfach das Table-Attribut im .__ platzieren. Unterklassen zur Angabe des zugeordneten Tabellennamens (Table-Attribut ist eine neue data-Annotation und wurde dem System.ComponentModel.DataAnnotations-Namensraum in CTP5 hinzugefügt.

Wenn Sie eine fließende API bevorzugen, können Sie mit .__ eine TPT-Zuordnung erstellen. ToTable () -Methode:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<BankAccount>().ToTable("BankAccounts");
    modelBuilder.Entity<CreditCard>().ToTable("CreditCards");
}
3
user3285954

Bei der Verwendung von Unterklassen muss die Spalte Diskriminator zwischen den einzelnen Unterklassen unterscheiden.

1
mathieu

Da sowohl "GiftCouponPayment" als auch "ClubCardPayment" von "PaymentComponent" abgeleitet sind, verwendet EF keine separaten Tabellen und benötigt diese Spalte. Wenn Sie ein anderes Verhalten wünschen, müssen Sie den standardmäßigen Tabellenzugriff überschreiben und die Felder Ihren Klassen zuordnen (was Sie meiner Meinung nach nicht tun möchten). Von Entität weiß ich zuerst, dass es einen Weg durch die Vorlage gibt, die die Tabellen erstellt. 
.__ Das Gleiche gilt für den Namen der Fremdschlüsselspalte. EF verwendet auf diese Weise den Namen für Schlüssel-/Fremdschlüsselnamen. Wenn Sie die Tabelle nach Ihren Wünschen formatieren möchten, müssen Sie alles selbst machen, was zu der Frage führt, warum EF überhaupt verwendet wird.
Gibt es einen bestimmten Grund, warum Sie das tun wollen, abgesehen von Kosmetika?

0
DerApe

Um die Discriminator-Spalte aus der Tabelle zu vermeiden, müssen Sie der abgeleiteten Klasse lediglich die Anmerkung [NotMapped] hinzufügen.

0
Valeriy

Beispielcode zum Entfernen der Discriminator-Spalte und zum Abrufen der Spalte PaymentId als Diskriminator, wodurch beide Fragen gelöst werden. Basierend auf Microsofts Fluent Api-Originaldokumentation.

https://msdn.Microsoft.com/en-us/library/jj591617%28v=vs.113%29.aspx?f=255&MSPPError=-2147217396

public enum MyEnum
{ 
    Value1, Value2
}

public class MyBaseClass

{ 
    [NotMapped]
    public MyEnum PaymentId { get; protected set; }
}

public class DerivedOne: MyBaseClass
{
    public DerivedOne()
    {
        PaymentId = MyEnum.Value1;
    } 
}

public class DerivedTwo: MyBaseClass
{
    public DerivedTwo()
    {
        PaymentId = MyEnum.Value2;
    }
}

public class MyDbContext : DbContext
{
    DbSet<MyBaseClass> MyBaseClass { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<MyBaseClass>()
            .Map<DerivedOne>(x => x.Requires("PaymentId").HasValue((int)PaymentId.Value1))
            .Map<DerivedTwo>(x => x.Requires("PaymentId").HasValue((int)PaymentId.Value2));
    }
}
0
Ogglas