LINQ to SQL断开连接的更新对象来自不同的数据上下文

4

链接

我正在使用C#的ASP.NET,并尝试使用linq to sql更新数据上下文,就像上面链接的博客所展示的那样。我按照说明在表中创建了时间戳字段,并使用以下方法:

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属性显示为空。我不确定它是否应该这样。

我拥有的每一本书和资源都说这是正确的方法,但它们都没有详细讲述这个TimeStamp属性。

我知道这很快很容易解决,如果有人知道,请告诉我。


打开日志记录并将DataContext.Log指向StreamWriter,以查看生成此更新所需的TSQL和参数。 - DamienG
2个回答

3

既然您说您在表中创建了时间戳字段,我想知道如果在以后添加此列的情况下,列属性是否设置正确。您可能需要在DBML设计器中检查TimeStamp列的属性。确保:

AutoGenerated = true
Auto-Sync = Always
Time Stamp = True
Update Check = Never

服务器数据类型应为rowversion NOT NULL
如果没有设置为自动生成并始终同步,由于在插入时未更改行版本,因此不会返回行版本。尽管该值由数据库生成,但DataContext需要知道这一点,以便能够正确处理它。
另外,现在您有了一个时间戳列,所有其他列的UpdateCheck都应设置为Never

1

如果您有一个时间戳列,那么要更新记录(从普通对象):是的,我希望必须进行分配。否则,您将失去使用时间戳进行乐观并发检查的能力。

思路是,当您获取(断开连接的)对象时,复制时间戳。然后,在更新时,您可以使用此列来验证没有其他人编辑了该行。

有两种常见情况:

1:如果您只执行短暂的操作,请先从数据库中获取记录-对对象进行更改,然后仅使用相同的数据上下文SumbitChanges()。数据上下文将为您处理并发。

2:如果您正在断开对象(例如将其传递给客户端应用程序一段时间),那么请使用类似序列化的东西(LINQ-to-SQL对象支持DataContractSerializer(可选;您需要启用它))。因此,在服务器上对对象进行序列化,将其传递到客户端-客户端对其副本进行更改并将其传递回。服务器对其进行反序列化并使用Attach()和SubmitChanges()。内存中的记录应仍具有从数据库中提取时拥有的时间戳,因此我们可以在涵盖记录断开所有时间的情况下执行乐观并发。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接