【问题标题】:InvalidOperationException on EFEF 上的 InvalidOperationException
【发布时间】:2014-09-17 05:26:45
【问题描述】:

我正在使用 WPF MVVM Pettern 和 我在 SQL Server 2012 上有一个简单的表,它的 ID(key) 列是在一个名为 PersonInsert 的 StoredProcedure 中计算的:(这是简化的,但计算的内容比这更复杂,无论如何它是一个 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 Code-First 来处理数据并映射到 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 异常并显示一条消息:

对数据库的更改已提交成功,但更新对象上下文时出错。 ObjectContext 可能处于不一致的状态。内部异常消息:保存或接受更改失败,因为多个“Shoniz.Guard.WPFGuardApplication.Person”类型的实体具有相同的主键值。确保显式设置的主键值是唯一的。确保在数据库和实体框架模型中正确配置了数据库生成的主键。使用实体设计器进行数据库优先/模型优先配置。使用“HasDatabaseGeneratedOption”流式 API 或“DatabaseGeneratedAttribute”进行 Code First 配置。

他是对的!数据提交成功!我也是对的,因为我的 ID(key) 列计算正确,而且它是完全唯一的。要么我在 ID 上使用了 DatabaseGeneratedAttributenone 值,但结果是一样的:(

即使我重新查询数据库以检查重复键,我也没有发现任何东西!

  1. 为什么会抛出这个异常?
  2. 如何防止这种情况发生?
  3. 还有什么可以忽略db.SaveChanges()之后的变化吗?

【问题讨论】:

    标签: c# .net vb.net entity-framework


    【解决方案1】:

    首先将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
    

    【讨论】:

    • 非常感谢 Mohandes,我很困惑如何告诉 EF 这是我新生成的 ID。我认为 Select @ID 必须将新 ID 返回给 Ef,因此我试图使我的模型可观察(使用 INotifyPropertyChanged),但我不认为 在我使用 SELECT 之前没有从 SQL 返回值 .再次感谢你:)
    猜你喜欢
    • 2021-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多