http://geekswithblogs.net/michelotti/archive/2007/12/17/117791.aspx
我正在使用带有C#的ASP.NET并尝试使用linq来更新上面链接的博客上显示的数据上下文。我正如上所述在表中创建了timestamp字段,并使用以下方法:
private void updateRecord(TableName updatedRecord)
{
context db = new context();
db.TableName.Attach(updatedRecord,true);
db.SubmitChanges();
}
我的问题是,你是否应该在尝试调用数据上下文中的Attach方法之前将timeStamp字段分配给updatedRecord中的任何内容?
当我运行此代码时,我得到以下异常:System.Data.Linq.ChangeConflictException: Row not found or changed.
我更新了所有字段,包括在将对象传递给此更新方法之前我正在更新的记录的主键。在调试期间,对象的TimeStamp属性显示为null。我不确定它是否应该是这样的。
我所说的每本书和资源都说这是实现它的方法,但是没有一本关于这个TimeStamp属性的详细信息。
我知道这很快捷,所以如果有人知道,请告诉我。
答案 0 :(得分:3)
由于您说您在表中创建了时间戳字段,我想知道,如果稍后添加此列,则可能无法正确设置列属性。 您可能想要检查DBML设计器中TimeStamp列的属性。确保:
AutoGenerated = true
Auto-Sync = Always
Time Stamp = True
Update Check = Never
服务器数据类型应为rowversion NOT NULL
如果未将其设置为自动生成并始终同步,则不会从插入返回行版本,因为插入完成后您尚未更改行版本。即使这个值是由数据库生成的,DataContext也需要知道这一点,以便它可以正确处理它。
此外,既然您有时间戳列,则UpdateCheck
应设置为Never
所有其他列。
答案 1 :(得分:1)
如果您有时间戳列,那么更新记录(来自vanilla对象):是的,我希望必须分配它。否则,您将失去使用时间戳进行乐观并发检查的能力。
您的想法是在获取(断开连接的)对象时获取时间戳的副本,然后在更新时可以使用此列来验证没有其他人编辑过该行。
有两种常见情况:
1:如果你只是执行一个短暂的操作,首先从数据库中取出记录 - 对对象进行更改,然后简单地使用SumbitChanges()[所有具有相同的数据上下文]。数据上下文将为您处理并发。
2:如果要断开对象(例如将其传递给客户端应用程序一段时间),则使用类似序列化的东西(LINQ-to-SQL对象支持DataContractSerializer(可选;您需要启用它))。因此,在服务器上序列化对象,将其传递给客户端 - 客户端对其副本进行更改并将其传回。服务器反序列化它并使用Attach()和SubmitChanges()。内存中的记录应该仍然具有从数据库中提取时的时间戳,因此我们可以在记录断开的所有时间内执行乐观并发。