【问题标题】:EF4 - update [Table] set @p = 0 whereEF4 - 更新 [表] 设置 @p = 0 其中
【发布时间】:2011-06-03 20:16:17
【问题描述】:

在浏览 SQL 分析器时,我注意到 EF4 生成了以下查询。

exec sp_executesql N'declare @p int
update [dbo].[User]
set @p = 0
where (([UserID] = @0) and ([RowVersion] = @1))
select [RowVersion]
from [dbo].[User]
where @@ROWCOUNT > 0 and [UserID] = @0',N'@0 int,@1 binary(8)',@0=1,@1=0x000000000042DDCD

我不确定为什么 EF4 会生成这个,而我实际上并没有更新 UnitOfWork 中 User 表的任何列。运行此查询会更新 RowVersion 列(时间戳数据类型),这会导致下一个 UnitOfWork 中出现 OptimisticConcurrencyException。

通过谷歌搜索,我找到了这个link,这证实了其他人也遇到了这种情况,但还没有找到解决方案。

非常感谢任何指针。

编辑:复制问题的示例代码。

User 和 Session 表具有外键关系。此外,在 EF4 中,我已将两个实体的 RowVersion 列的 "Concurrency Mode" 属性设置为 Fixed

以下是复制场景的示例方法。

 private static void UpdateSession()
    {
        using (var context = new TestEntities())
        {
            context.ContextOptions.ProxyCreationEnabled = false;

            var session = context.Users.Include("Sessions").First().Sessions.First();
            session.LastActivityTime = DateTime.Now;

            context.ApplyCurrentValues("Sessions", session);

            context.SaveChanges();
        }
    }

我从 Sql profiler 中看到以下由 EF4 生成的查询。

exec sp_executesql N'update [dbo].[Session]
set [LastActivityTime] = @0
where (([SessionID] = @1) and ([RowVersion] = @2))
select [RowVersion]
from [dbo].[Session]
where @@ROWCOUNT > 0 and [SessionID] = @1',N'@0 datetime2(7),@1 int,@2 binary(8)',@0='2011-06-20 09:43:30.6919628',@1=1,@2=0x00000000000007D7

接下来的查询很奇怪。

    exec sp_executesql N'declare @p int
update [dbo].[User]
set @p = 0
where (([UserID] = @0) and ([RowVersion] = @1))
select [RowVersion]
from [dbo].[User]
where @@ROWCOUNT > 0 and [UserID] = @0',N'@0 int,@1 binary(8)',@0=1,@1=0x00000000000007D3

【问题讨论】:

  • 在您调用SaveChanges 之前,您的User 实体的状态是什么?您是否还更改了指向User 的任何关系?
  • @Ladislav Mrnka - 我检查了 ObjectStateManager 并且在 SaveChanges 之前用户实体的状态是未更改的。是的,我修改了一些与用户实体相关的实体,并且在调用 SaveChanges 时,除了所需/预期的 sql 之外,还会生成上述 sql。
  • 那么关系呢?您是否更改了与该特定用户的任何关系?
  • @Ladislav Mrnka - 恐怕我没有正确回答您的问题。你的意思是如果我改变了用户实体的导航属性的任何属性?如果是这样,是的,我正在这样做。
  • 以防万一如果您不修改导航属性,这个奇怪的更新是否仍然存在?

标签: entity-framework entity-framework-4


【解决方案1】:

不确定这对您来说是否仍然存在问题,但这是 MS http://support.microsoft.com/kb/2390624 的修补程序

【讨论】:

  • 知识库链接解释了该场景。但是,您需要打开 MSDN 票证才能获得修补程序。我刚拿到我的并安装它解决了问题。
【解决方案2】:

在另一个论坛上找到了这个链接,并且能够下载 Kris Ivanov 提到的修补程序。

http://support.microsoft.com/hotfix/KBHotfix.aspx?kbnum=2390624

【讨论】:

    【解决方案3】:

    不确定 EF4,但在 4.1 中,我们通过将 rowversion/timestamp 设置为 concurrenttoken = false 来关闭它。

    我们这样做是因为

    1. 这是我们数据库中的计算字段
    2. 不应由应用程序更改(在我们的例子中)

    【讨论】:

    • 因此它应该设置为true。否则,您可以完全从数据库中删除该列,因为您没有按预期使用它 - 来处理并发。
    • 就我而言,我必须将 Rowversion 列的 ConcurrencyMode 设置为 Fixed 以便 EF4 在更新/删除期间检查乐观并发问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-25
    • 2011-01-03
    • 1970-01-01
    相关资源
    最近更新 更多