我正在使用VS1010RC和POCO自我跟踪T4模板。
在我的WCF更新服务方法中,我使用类似于以下内容的内容:
using (var context = new MyContext())
{
context.MyObjects.ApplyChanges(myObject);
context.SaveChanges();
}
这个工作正常,直到我在实体上设置ConcurrencyMode = Fixed,然后我得到一个异常。由于SQL语句在WHERE子句中使用已更改的实体值,因此上下文似乎不知道以前的值。
使用ConcurrencyMode = Fixed?
时,正确的方法是什么?答案 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可能是一个不错的选择,这完全取决于您的要求。