LINQ to SQL 从不同数据上下文断开更新对象

问题描述 投票:0回答:2

链接

我正在将 ASP.NET 与 C# 结合使用,并尝试使用 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 属性显示为 null。我不确定是否应该这样。

我拥有的每本书和资源都说这是这样做的方法,但它们都没有详细介绍这个 TimeStamp 属性。

我知道这又快又简单,所以如果有人知道,请告诉我。

c# linq-to-sql timestamp
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()。内存中的记录应该仍然具有从数据库中提取时的时间戳,因此我们可以在记录断开连接的所有时间内执行乐观并发。

© www.soinside.com 2019 - 2024. All rights reserved.