主要违规:继承使用EF代码优先 [英] Primary Key Violation: Inheritance using EF Code First

查看:95
本文介绍了主要违规:继承使用EF代码优先的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下的EF代码第一个代码。我收到以下异常:


'GiftCouponPayment'不包含标识列。




表在数据库中成功创建。但是,如何摆脱这个异常呢?另外,这个异常的原因是什么?



注意:我可以使用任何表模式,因为域模型(使用代码第一个描述)被保留(和数据可以查询)。





继续此例外,还有一个例外如下:


保存不暴露其关系的外键属性的实体时出错。 EntityEntries属性将返回null,因为单个实体不能被识别为异常的源。通过在您的实体类型中暴露外键属性,可以更容易地处理异常处理。有关详细信息,请参阅InnerException。



{违反PRIMARY KEY约束PK_dbo.PaymentComponent。无法在对象dbo.PaymentComponent中插入重复键。 \\ n该声明已被终止。}


参考


  1. 实体框架:拆分表多个表

注意:生成的数据库模式如下所示。 p>



代码:

  public class MyInitializer:CreateDatabaseIfNotExists< NerdDinners> 
{
//每个表只能创建一个标识列。
protected override void Seed(NerdDinners context)
{
//context.Database.ExecuteSqlCommand(\"CREATE UNIQUE INDEX IX_Payment_PayedTime ON Payment(PayedTime));
context.Database.ExecuteSqlCommand(DBCC CHECKIDENT('Payment',RESEED,1));
context.Database.ExecuteSqlCommand(DBCC CHECKIDENT('GiftCouponPayment',RESEED,2));
context.Database.ExecuteSqlCommand(DBCC CHECKIDENT('ClubCardPayment',RESEED,3));
}
}

//System.Data.Entity.DbContext来自EntityFramework.dll
public class NerdDinners:System.Data.Entity.DbContext
{
public NerdDinners(string connString):base(connString)
{
}

protected override void OnModelCreating(DbModelBuilder modelbuilder)
{
//流利的API - 多重删除
modelbuilder.Conventions.Remove< PluralizingTableNameConvention>();

//流利的API - 每个混合类型表(TPC)
modelbuilder.Entity< GiftCouponPayment>()
.Map(m =>
{
m.MapInheritedProperties();
m.ToTable(GiftCouponPayment);
});

modelbuilder.Entity< ClubCardPayment>()
.Map(m =>
{
m.MapInheritedProperties();
m.ToTable ClubCardPayment);
});
}

public DbSet< GiftCouponPayment> GiftCouponPayments {get;组; }
public DbSet&ClubCardPayment> ClubCardPayments {get;组; }
public DbSet< Payment>付款{get;组; }
}

public abstract class PaymentComponent
{
public int PaymentComponentID {get;组; }
public int MyValue {get;组; }
public abstract int GetEffectiveValue();


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

公共部分类ClubCard付款:PaymentComponent
{
public override int GetEffectiveValue()
{
return MyValue ;
}
}

public partial class付款
{
public int PaymentID {get;组; }
public List< PaymentComponent> PaymentComponents {get;组; }
public DateTime PayedTime {get;组; }
}

客户端:

  static void Main(string [] args)
{
Database.SetInitializer< NerdDinners>(new MyInitializer());
string connectionstring =Data Source =; Initial Catalog = NerdDinners; Integrated Security = True; Connect Timeout = 30;

使用(var db = new NerdDinners(connectionstring))
{
GiftCouponPayment giftCouponPayment = new GiftCouponPayment();
giftCouponPayment.MyValue = 250;

ClubCard付款clubCardPayment =新的ClubCard付款();
clubCardPayment.MyValue = 5000;

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

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

int recordsAffected = db.SaveChanges();
}
}


解决方案

看到我对TPC的初步建议是不正确的,因为你也在基类中使用FK - 你看到 PaymentComponent 表?在TPC继承的情况下不应该是。尝试使用TPT继承(从映射中删除 MapInheritedProperties )。这将以相同的正确数据库结束。不要使用杂草该ID将仅由 PaymentComponent 表中的标识列(目前为止)进行控制。


I have following EF code first code. I am getting the following exception:

'GiftCouponPayment' does not contain an identity column.

The tables are successfully created in database. However, how can I get rid of this exception? Also, what is the reason for this exception?

Note: I am okay with any table schema as longs as the domain model (described using code first) is retained (and the data can be queried).

After continuing this exception, there is a another exception as below:

An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. See the InnerException for details.

{"Violation of PRIMARY KEY constraint 'PK_dbo.PaymentComponent'. Cannot insert duplicate key in object 'dbo.PaymentComponent'.\r\nThe statement has been terminated."}

Reference:

  1. Entity Framework: Split table into multiple tables

Note: The resulting database schema is as shown below.

Code:

public class MyInitializer : CreateDatabaseIfNotExists<NerdDinners>
{
    //Only one identity column can be created per table.
    protected override void Seed(NerdDinners context)
    {
        //context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX IX_Payment_PayedTime ON Payment (PayedTime)");
        context.Database.ExecuteSqlCommand("DBCC CHECKIDENT ('Payment', RESEED, 1)");
        context.Database.ExecuteSqlCommand("DBCC CHECKIDENT ('GiftCouponPayment', RESEED, 2)");
        context.Database.ExecuteSqlCommand("DBCC CHECKIDENT ('ClubCardPayment', RESEED, 3)");
    }
}

//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)
    {
        //Fluent API - Plural Removal
        modelbuilder.Conventions.Remove<PluralizingTableNameConvention>();

        //Fluent API - Table per Concrete Type (TPC)
        modelbuilder.Entity<GiftCouponPayment>()
            .Map(m =>
            {
                m.MapInheritedProperties();
                m.ToTable("GiftCouponPayment");
            });

        modelbuilder.Entity<ClubCardPayment>()
            .Map(m =>
            {
                m.MapInheritedProperties();
                m.ToTable("ClubCardPayment");
            });
    }

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

public abstract class PaymentComponent
{
    public int PaymentComponentID { get; set; }
    public int MyValue { 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; }
}

Client:

    static void Main(string[] args)
    {
        Database.SetInitializer<NerdDinners>(new MyInitializer());
        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;

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

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

解决方案

I see that my initial advice about TPC wasn't correct because you are also using FK in the base class - do you see the PaymentComponent table? It should not be there in case of TPC inheritance. Try to use TPT inheritance (remove MapInheritedProperties from your mapping). This will end with the same correct database. Don't use reseed. The Id will be controlled just by identity column in PaymentComponent table (as it is at the moment).

这篇关于主要违规:继承使用EF代码优先的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆