【问题标题】:Entity Framework Many-to-Many Insert throws error Cannot insert explicit value for identity column in table when IDENTITY_INSERT is set to OFF当 IDENTITY_INSERT 设置为 OFF 时,实体框架多对多插入引发错误无法在表中插入标识列的显式值
【发布时间】:2016-08-05 17:11:23
【问题描述】:

我从数据库创建了一个创建代码优先的模型,所以我已经设置了我的实体和上下文。 这是有问题的表的图表。 Many to Many relation diagram 如果有意义的话,这种关系可以知道哪个 Payment 涵盖了哪些订单。 我正在尝试通过将 SalesOrder 的实例添加到 EF 中的 payment.SalesOrders 来向 PaymentSalesOrder 添加一条记录。 调用 SaveChanges() 时出现此错误:

错误代码

当 IDENTITY_INSERT 设置为 OFF 时,无法为表“PaymentSalesOrder”中的标识列插入显式值。

这是代码,基本上我查询当前客户的数据库并包括他的付款和订单。 我将付款分配给销售订单并更改付款和 salesOrder 以反映它们的可用性。 最后,我将 salesOrder 添加到付款并调用 SaveChanges()。

我有一个客户在数据库中有一个订单和一个付款,因此此代码中的所有实体都填充了正确的数据。

代码

Using db As New eRestaurantEF.Context
        If _customer Is Nothing Then
            Exit Sub
        End If
        Dim tmpCustomer As eRestaurantEF.Customer
        tmpCustomer = (From tmp In db.Customers.Include("Payments").Include("SalesOrders")
                       Where tmp.customerID = _customer.customerID
                       Select tmp).FirstOrDefault

        For Each paymentRow As eRestaurantEF.Payment In tmpCustomer.Payments
            If paymentRow.PaymentRemainder > 0 Then

                For Each orderRow As eRestaurantEF.SalesOrder In tmpCustomer.SalesOrders
                    db.SalesOrders.Attach(orderRow)
                    db.Entry(orderRow).State = Entity.EntityState.Unchanged
                    If paymentRow.PaymentRemainder > 0 Then

                        If Not orderRow.FullyPaid Then

                            If paymentRow.PaymentRemainder >= orderRow.Remainder Then
                                Dim remainder As Decimal
                                remainder = paymentRow.PaymentRemainder
                                remainder -= orderRow.Remainder

                                paymentRow.PaymentRemainder = remainder
                                orderRow.Remainder = 0
                                orderRow.IsPaid = True
                                orderRow.IsCredit = True
                                orderRow.FullyPaid = True
                                paymentRow.SalesOrders.Add(orderRow)

                            ElseIf paymentRow.PaymentRemainder <= orderRow.Total Then
                                Dim remainder As Decimal
                                remainder = paymentRow.PaymentRemainder
                                remainder -= orderRow.Remainder

                                If remainder = 0 Then
                                    paymentRow.PaymentRemainder = 0
                                    orderRow.Remainder = 0
                                    orderRow.IsPaid = True
                                    orderRow.IsCredit = True
                                    orderRow.FullyPaid = True
                                    paymentRow.SalesOrders.Add(orderRow)
                                    Exit For

                                ElseIf remainder < 0 Then
                                    paymentRow.PaymentRemainder = 0
                                    orderRow.Remainder = Math.Abs(remainder)
                                    orderRow.IsPaid = False
                                    orderRow.IsCredit = True
                                    orderRow.FullyPaid = False
                                    orderRow.Payments.Add(paymentRow)
                                    Exit For

                                End If
                            End If
                        End If
                    End If
                Next 'OrdersList
            End If
        Next 'PaymentsList

        db.SaveChanges()
    End Using

这里是关系表的 Fluent Api:

modelBuilder.Entity(Of Payment)() _
    .HasMany(Function(e) e.SalesOrders) _
    .WithMany(Function(e) e.Payments) _
    .Map(Function(m) m.ToTable("PaymentSalesOrder").MapLeftKey("Payment_ID").MapRightKey("SalesOrder_No"))

PaymentSalesOrder 表中的两个 FK 都是在数据库中创建的复合键的一部分,以确保没有重复的行。 我什至尝试删除密钥并将其更改为唯一索引,但问题仍然存在。 这是来自 Sql 的表脚本:

CREATE TABLE [dbo].[PaymentSalesOrder](
    [Payment_ID] [int] IDENTITY(1,1) NOT NULL, <---- Here is the culprit remove the identity from this column
    [SalesOrder_No] [int] NOT NULL,
    CONSTRAINT [PK_PaymentSalesOrder] PRIMARY KEY CLUSTERED 
(
    [Payment_ID] ASC,
    [SalesOrder_No] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[PaymentSalesOrder]  WITH CHECK ADD  CONSTRAINT [FK_PaymentSalesOrder_Payment] FOREIGN KEY([Payment_ID])
REFERENCES [dbo].[Payment] ([PaymentID])
GO
ALTER TABLE [dbo].[PaymentSalesOrder] CHECK CONSTRAINT [FK_PaymentSalesOrder_Payment]
GO
ALTER TABLE [dbo].[PaymentSalesOrder]  WITH CHECK ADD  CONSTRAINT [FK_PaymentSalesOrder_SalesOrder] FOREIGN KEY([SalesOrder_No])
REFERENCES [dbo].[SalesOrder] ([SalesOrderNo])
GO

ALTER TABLE [dbo].[PaymentSalesOrder] CHECK CONSTRAINT [FK_PaymentSalesOrder_SalesOrder]
GO

我为这篇长文道歉,但这真的很令人抓狂,我看不出问题出在哪里。 我正在考虑把多对多的关系全部去掉,但是不知道原因就放弃对我来说并不容易,如果我再次遇到它怎么办。

【问题讨论】:

    标签: sql-server vb.net entity-framework many-to-many


    【解决方案1】:

    错误清楚地表明您正在尝试在 IDENTITY 列中插入一个值,但您无法将值插入到 IDENTITY 列中,在您的情况下是 Payment_IDPaymentSalesOrder 表。 IDENTITY 列会在您插入新行时自动生成其值,方法是增加 INCREMENT 提供的值,在您的情况下为 1。我的意思是,每当您插入新行时,Payment_ID 的值将自动从 1 开始插入,并且会为每个新行保持递增 1。

    您可以在 IDENTITY here 上获取更多信息。

    希望你现在清楚

    【讨论】:

    • 谢谢@jonju,答案一直就在我面前,我看不到。我刚刚从表中删除了身份。现在我必须编写一个脚本来在生产数据库中更改它。再次感谢
    猜你喜欢
    • 2019-11-29
    • 2014-05-24
    • 2017-10-26
    • 2016-05-13
    • 2016-08-18
    • 2019-03-10
    • 2020-06-06
    相关资源
    最近更新 更多