如何在N层方案中利用EF 4.0 POCO自我跟踪实体进行并发检查?

时间:2010-03-05 16:38:14

标签: entity-framework concurrency poco n-tier-architecture

我正在使用VS1010RC和POCO自我跟踪T4模板。

在我的WCF更新服务方法中,我使用类似于以下内容的内容:

using (var context = new MyContext())
{
  context.MyObjects.ApplyChanges(myObject);
  context.SaveChanges();
}

这个工作正常,直到我在实体上设置ConcurrencyMode = Fixed,然后我得到一个异常。由于SQL语句在WHERE子句中使用已更改的实体值,因此上下文似乎不知道以前的值。

使用ConcurrencyMode = Fixed?

时,正确的方法是什么?

2 个答案:

答案 0 :(得分:2)

以前的值必须在您的对象中。

假设您有一个属性ConcurrencyToken

public class MyObject
{
    public Guid Id { get; set; }
    // stuff
    public byte[] ConcurrencyToken { get; set; }
}

现在您可以在该属性上设置ConcurrencyMode.Fixed。您还需要配置数据库以自动更新它。

查询数据库时,它会有一些值:

var mo = Context.MyObjects.First();
Assert.IsNotNull(mo.ConcurrencyToken);

现在您可以分离或序列化对象,但是您需要包含ConcurrencyToken。因此,如果您将对象数据放在Web表单上,则需要将ConcurrencyToken序列化为字符串并将其放入隐藏的输入中。

当您ApplyChanges时,您需要加入ConcurrencyToken

Assert.IsNotNull(myObject.ConcurrencyToken);
using (var context = new MyContext())
{
  context.MyObjects.ApplyChanges(myObject);
  context.SaveChanges();
}

ConcurrencyMode.Fixed更改UPDATE SQL。通常它看起来像:

UPDATE [dbo].[MyObject]
SET --stuff
WHERE [Id] = @0

使用ConcurrencyMode.Fixed看起来像:

UPDATE [dbo].[MyObject]
SET --stuff
WHERE [Id] = @0 AND [ConcurrencyToken] = @1

...因此,如果有人在您读取原始并发令牌与保存时间之间更新了行,则UPDATE将影响0行而不是1.EFT会在此处引发并发错误情况下。

因此,如果其中任何一项不适合您,第一步是使用SQL事件探查器查看生成的UPDATE

答案 1 :(得分:0)

标记,

创建为“自跟踪实体”的对象不能被视为纯POCO;

原因如下: 如果您的客户端使用STE T4模板中生成的代理,则STE仅适用。 变更跟踪以及您的服务仅适用于这些生成的代理。

在纯粹的POCO世界(互操作性,并非所有.Net 4.0客户端,......),你不能把 对你客户的约束。例如,Facebook不会编写可以的服务 只处理.Net 4.0客户端。

在某些环境中,STE可能是一个不错的选择,这完全取决于您的要求。