InvalidOperationException on EF
本文关键字:EF on InvalidOperationException | 更新日期: 2023-09-27 18:22:04
我正在使用WPF MVVM Pettern和我在SQL Server 2012上有一个简单的表,它的ID
(键(列是在存储过程中计算的,称为PersonInsert
:(这是简化的,但计算的内容比这更复杂,无论如何它终于是一个int
(
USE [Guard]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[PersonInsert]
@FName NVARCHAR(50) ,
@LName NVARCHAR(50) ,
@ID INT = NULL OUTPUT
AS
BEGIN
BEGIN TRY
SELECT @ID = ISNULL(MAX(ID), 0) + 1
FROM dbo.Person
INSERT INTO [dbo].[Person]
( [ID] ,
[FName] ,
[LName]
)
VALUES ( @ID ,
@FName ,
@LName
)
END TRY
BEGIN CATCH
DECLARE @ErrMsg NVARCHAR(MAX) ,
@ErrSvr INT ,
@ErrStt INT
SELECT @ErrMsg = ERROR_MESSAGE() + '|' + ERROR_PROCEDURE() + '|'
+ CAST(ERROR_LINE() AS NVARCHAR(5)) ,
@ErrSvr = ERROR_SEVERITY() ,
@ErrStt = ERROR_STATE()
RAISERROR (@ErrMsg, @ErrSvr, @ErrStt)
END CATCH
END
GO
在 .net 端,我使用 EF 6.1 代码优先来处理数据并映射到 SP,因此我有如下OnModelCreating
:
modelBuilder.Entity(Of Person)().MapToStoredProcedures(
Sub(x)
x.Insert(Function(e) e.HasName("[dbo].[PersonInsert]"))
x.Update(Function(e) e.HasName("[dbo].[PersonUpdate]"))
x.Delete(Function(e) e.HasName("[dbo].[PersonDelete]"))
End Sub)
我的模型是:
<Table("Person")> _
Partial Public Class Person
<DatabaseGenerated(DatabaseGeneratedOption.None), Key> _
Public Property ID As Integer
Public Property FName As String
Public Property LName as String
End Class
现在奇怪的是,当我第一次尝试插入数据(添加新人员(时,db.SaveChanged()
效果很好,但第二次它会抛出 InvalidOperation 异常并显示一条消息:
已成功提交对数据库的更改,但在更新对象上下文时出错。对象上下文可能处于不一致的状态。内部异常消息:保存或接受更改失败,因为类型为"Shoniz.Guard.WPFGuardApplication.Person"的多个实体具有相同的主键值。确保显式设置的主键值是唯一的。确保在数据库和实体框架模型中正确配置了数据库生成的主键。使用实体设计器进行数据库优先/模型优先配置。使用"HasDatabaseGenerated Option"fluent API 或 'DatabaseGenerated Attribute' 进行代码优先配置。
他是对的!数据已成功提交!我也是对的,因为我的ID
(键(列计算正确,它是完全唯一的。要么我在 ID 上使用了没有值的数据库生成属性,但结果是相同的:(
即使我重新查询数据库以检查重复的键,我也一无所获!
- 为什么抛出此异常?
- 我怎样才能防止这种情况发生?
- 无论如何可以忽略
db.SaveChanges()
后的更改吗?
首先将DatabaseGeneratedOption.None
更改为DatabaseGeneratedOption.Indetity
最后将存储过程更改为:
BEGIN TRY
SELECT @ID = ISNULL(MAX(ID), 0) + 1
FROM dbo.Person
INSERT INTO [dbo].[Person]
( [ID] ,
[FName] ,
[LName]
)
VALUES ( @ID ,
@FName ,
@LName
)
--You have to tell EF this is returned Id of inserted person
SELECT @ID as ID
END TRY