主键冲突:使用EF code首先继承主键、冲突、code、EF

2023-09-03 04:15:42 作者:虚伪的世界,让我泪留满面

我有以下EF code首先code。我收到以下异常:

  

GiftCouponPayment'不包含标识列。

该表在数据库创建成功。但是,我怎么能摆脱这种异常?此外,什么是这个异常的原因?

注:我没关系与任何表模式作为多头的域模型被保留(和数据可查询)(使用code首先描述)

继续此异常后,有如下一个又一个例外:

  

同时节省不为他们的关系曝光外键属性的实体时出错。因为一个单独的实体不能认定为异常的源EntityEntries属性将返回空。处理异常的同时节省可通过在实体类型揭露外键的属性更容易。见的InnerException了解详细信息。

     

{违反PRIMARY KEY约束'PK_dbo.PaymentComponent'。不能插入对象dbo.PaymentComponent重复键。\ r \ n此语句已终止。}

参考

Entity框架:分割表到多个表

注意:生成的数据库架构如下图所示。

code:

 公共类MyInitializer:CreateDatabaseIfNotExists< NerdDinners>
{
    //只有一个标识列每个表只能创建。
    保护覆盖无效的种子(NerdDinners上下文)
    {
        //context.Database.ExecuteSqlCommand("CREATE唯一索引IX_Payment_PayedTime付款(PayedTime));
        context.Database.ExecuteSqlCommand(DBCC CHECKIDENT('支付',RESEED,1));
        context.Database.ExecuteSqlCommand(DBCC CHECKIDENT('GiftCouponPayment',RESEED,2));
        context.Database.ExecuteSqlCommand(DBCC CHECKIDENT('ClubCardPayment',RESEED,3));
    }
}

//System.Data.Entity.DbContext是EntityFramework.dll
公共类NerdDinners:System.Data.Entity.DbContext
{
    公共NerdDinners(字符串CONNSTRING):基地(CONNSTRING)
    {
    }

    保护覆盖无效OnModelCreating(DbModelBuilder模型构建器)
    {
        //流利的API  - 复数去除
        modelbuilder.Conventions.Remove&其中; PluralizingTableNameConvention>();

        //流利的API  - 表每个具体类型(TPC)
        modelbuilder.Entity< GiftCouponPayment>()
            .MAP(米=>
            {
                m.MapInheritedProperties();
                m.ToTable(GiftCouponPayment);
            });

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

    公共DbSet< GiftCouponPayment> GiftCouponPayments {获得;组; }
    公共DbSet< ClubCardPayment> ClubCardPayments {获得;组; }
    公共DbSet<付款和GT;付款{获得;组; }
}

公共抽象类PaymentComponent
{
    公众诠释PaymentComponentID {获得;组; }
    公众诠释myvalue的{获得;组; }
    公共抽象INT GetEffectiveValue();
}

公共部分类GiftCouponPayment:PaymentComponent
{
    公众覆盖INT GetEffectiveValue()
    {
        如果(myvalue的&所述; 2000)
        {
            返回0;
        }
        返回myvalue的;
    }
}

公共部分类ClubCardPayment:PaymentComponent
{
    公众覆盖INT GetEffectiveValue()
    {
        返回myvalue的;
    }
}

公共部分类付款
{
    公众诠释PaymentID {获得;组; }
    公开名单< PaymentComponent> PaymentComponents {获得;组; }
    公开日期时间PayedTime {获得;组; }
}
 

客户端:

 静态无效的主要(字串[] args)
    {
        Database.SetInitializer&其中; NerdDinners>(新MyInitializer());
        字符串的ConnectionString =数据源=;初始目录= NerdDinners;集成安全性= TRUE;连接超时= 30;

        使用(VAR DB =新NerdDinners(的ConnectionString))
        {
            GiftCouponPayment giftCouponPayment =新GiftCouponPayment();
            giftCouponPayment.MyValue = 250;

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

            名单< PaymentComponent>谱曲=新的名单,其中,PaymentComponent>();
            comps.Add(giftCouponPayment);
            comps.Add(clubCardPayment);

            VAR支付=新的支付{PaymentComponents =谱曲,PayedTime = DateTime.Now};
            db.Payments.Add(付款);

            INT recordsAffected = db.SaveChanges();
        }
    }
 
EF使用CodeFirst创建数据库和表

解决方案

我看到,我对TPC初步意见是不正确的,因为你也是在基类中使用FK - 你看到 PaymentComponent 表?它不应该存在的情况下TPC继承。尝试使用TPT的继承(从你的映射删除 MapInheritedProperties )。这将结束与同正确的数据库。不要使用补种。该标识将只是身份列在 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:

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).