【问题标题】:Optimistic Concurrency using Stored Procedures in Entity Framework在实体框架中使用存储过程的乐观并发
【发布时间】:2013-08-28 20:53:58
【问题描述】:

在实体框架中,使用存储过程,我想使用乐观并发对我的表执行更新。如果不修改我现有的更新存储过程,我就无法让它工作。我正在尝试确定是否有一种方法可以映射我现有的存储过程,以便在没有更新行时发生并发异常。

一些背景资料:

  • 我已在我的 .edmx 文件中映射了更新存储过程(包括时间戳)列
  • 我现有的存储过程如下所示(实际的表名和列显然被省略了):

    UPDATE Table SET Column = @Column1, Column2 = @Column2 ....
    WHERE PK = @PK AND Timestamp = @Timestamp
    
    SELECT PK, Column1, Column2, ....., Timestamp
    FROM Table WHERE PK = @PK
    
  • 如果更新失败(由于时间戳不匹配),存储过程的选择部分仍然返回一行。

当我将存储过程修改为以下内容时:

   UPDATE Table SET Column = @Column1, Column2 = @Column2 ....
   WHERE PK = @PK AND Timestamp = @Timestamp

   IF @@ROWCOUNT > 0
       SELECT PK, Column1, Column2, ....., Timestamp
       FROM Table WHERE PK = @PK

然后一切按预期工作,并发错误发生。

或者,如果我让存储过程返回一个输出参数,并将该输出参数映射到实体框架的 .edmx 文件中的“行影响参数”,那么并发错误也会按预期工作。

这个解决方案(即使用输出参数)解释得最好,我发现,在这里: http://petermannerhult.wordpress.com/2010/10/01/entity-framework-4-with-optimistic-concurrency-and-stored-procedures/

上述步骤似乎都不是必需的,因为我假设实体框架可以只使用更新的行数来确定它是否应该引发并发异常。我在 ADO.NET 数据集中使用了这些完全相同的存储过程(具有乐观并发),没有任何问题。所以我的问题是,如何在不修改的情况下使用现有的存储过程在实体框架中启用乐观并发?

【问题讨论】:

  • 我不认为 EF 有问题。 EF 无权访问存储过程中更新语句的行数。因此,您必须通过检查 proc 中的行数或从 proc 返回行数来自己处理该检查,以便 EF 可以确定该行是否已更新。
  • @Satish 感谢您的回复,但您能解释一下为什么 EF 无法访问我的更新语句的行数吗?在 SQL Server 中执行存储过程时,该信息应该可用。例如,可以使用 SqlDataReader 的 RecordsAffected 属性访问它(请参阅msdn.microsoft.com/en-us/library/…)。鉴于这个精确的存储过程在 ADO.NET 中工作(具有乐观并发),它必须能够确定更新的行数。 EF 不能这样做有什么原因吗?
  • 看来 EF 本身并没有从存储过程执行中获得 RecordsAffected 属性。我可以推测出这种情况的各种原因,但最终只有 EF 产品开发人员可以肯定地说。这并不重要为什么,它只是不能那样工作。
  • @RBarryYoung 是的,不幸的是,我认为您可能是正确的。这也是我得出的结论。看来修改我的存储过程是完成这项工作的唯一方法:-(
  • 同意。而且由于OUTPUT参数也可以是可选的存储过程参数,你应该可以添加它而无需更改任何其他调用代码。

标签: c# entity-framework


【解决方案1】:

在 EDMX 设计器的存储过程映射窗口中,每个属性旁边都有两个复选框。 Use Original ValueRows Affected Parameter。如您所述,Rows Affected Parameter 要求您在 proc 中使用输出参数。但是,如果您选择Use Original Value 作为时间戳,它会比较它们并在两者不匹配时抛出OptimisticConcurrencyException。这应该允许您在无需修改过程的情况下获得异常。

【讨论】:

    【解决方案2】:

    如果您真的不想更改存储过程代码,可以将存储过程返回的 Timestamp 与传入其中的 Timestamp 进行比较。如果不同,那么您有一个并发错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-23
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 2015-06-27
      • 1970-01-01
      • 1970-01-01
      • 2014-01-25
      相关资源
      最近更新 更多