Rad*_*erz 4 linq linq-to-sql optimistic-concurrency
我正在使用 Linq 更新表中的单个列,请使用下面的虚构表格。
MyTable(PKID、ColumnToUpdate、SomeRandomColumn)
var row = (from x in DataContext.MyTable
where b.PKID == 5
select x).FirstOrDefault();
row.ColumnToUpdate = 20;
DataContext.SubmitChanges();
Run Code Online (Sandbox Code Playgroud)
这会将专栏更新为预期的内容,这并不奇怪。但是,当我检查生成的 SQL 命令时,它会执行以下操作:
UPDATE [dbo].[MyTable ]
SET [ColumnToUpdate ] = @p2
WHERE ([PKID] = @p0) AND ([SomeRandomColumn] = @p1)
Run Code Online (Sandbox Code Playgroud)
这是执行更新,但前提是所有列都与实体期望的值匹配,而不是单独引用主键列。
如果数据库列被另一个进程更改,这在这个特定项目中是非常可行的;例如。在获取要操作的行、计算要设置值的更改以及以一批行形式发出更新命令之间存在一个窗口。在这种情况下,查询将引发异常,从而导致部分更新,除非我捕获、重新加载数据并重新发送单个查询。它还有一个缺点,即行信息可能非常大(例如,包含 HTML 标记),并且整个信息都会传递给 SQL,并在处理较大批次时减慢系统速度。
有没有办法让 Linq / Entity 仅根据Where 子句中的 PK 列发出更新命令?
我从未在生产项目中使用过 LINQ-to-SQL,也从未意识到它默认应用乐观并发1 。
这是默认行为:
Timestamp/Rowversion列2,则所有列在 DBML 中都将“更新检查”设置为“始终”(主键列和计算列除外,即所有可更新列)。Timestamp/Rowversion列,则该列在 DBML 中将“时间戳”设置为“True”,并且所有列的“更新检查”=“从不”。“更新检查”或“时间戳”将列标记为并发令牌。这就是为什么在更新语句中您会在(不是)“随机”列上看到这些附加谓词。显然,模型中的表没有Timestamp/Rowversion列,因此更新会检查表中所有可更新列的值。
1乐观并发:更新记录时不设置排他锁,但更新时检查所有或选定列的现有值。如果其中一个列值在获取数据和保存数据之间被其他用户更改,则会发生更新异常。
2数据类型Timestamp或的列Rowversion在更新记录时自动递增,因此检测对此记录的所有并发更改。