我有一个程序在两台服务器上重复运行。
我需要在程序中选择和更新数据库记录,因此我需要来自EF的表锁或事务,否则程序的每个副本都可以选择和修改相同的记录。虽然第一个副本使数据库发生更改,但另一个副本不应运行相同的代码部分。
我在 EF 中找到了 TransactionScope,但它无法正常工作,因为当第一个副本运行时,我可以在 SQL Server MGM studio 中对该表进行许多选择和更新。
我有一个简短的代码片段,请验证它:
using (TransactionScope transaction = new TransactionScope())
{
//select some records which aren't locked by the other copy of the program
//condition: Locked==null
recipientsList = (from c in context.Recipients
where
c.SentToPlatform == false && c.PopupID != null &&
c.Message.MessageStatus == 2 && c.Locked == null
select c).Take(piecePerMinute).ToList();
foreach (var recipient in recipientsList)
{
//i need make some changes on the record, prevent it from the other copy of program
//I need to change locked column to true
recipient.Locked = true;
recipient.LockBy = ipAddress;
Console.Write("I");
Thread.Sleep(1000);
}
//close transaction
try
{
context.SaveChanges();
transaction.Complete();
} catch (Exception ex )
{
}
}
从技术上来说您要求的是一个长时间(呃)运行的事务,其隔离级别高于已提交读(默认级别)。没有足够的信息让我知道您是否想要 RepeatableRead 还是 Serialzable(以避免幻象插入)。
您可以通过执行以下操作来完成您的要求:
var opt = new TransactionOptions();
opt.IsolationLevel = IsolationLevel.Serializable;
using (var scope = new TransactionScope(TransactionScopeOption.Required, opt) ){
//read table code
//write table code
//save context & complete scope
}
照这样说,我非常怀疑这就是你真正想要的。可序列化事务可能会使数据库的大部分内容处于锁定状态。这意味着什么?以下是 Microsoft 对可序列化事务的描述:
SERIALIZABLE 指定以下内容:
- 语句无法读取已被其他事务修改但尚未提交的数据。
- 在当前事务完成之前,任何其他事务都不能修改当前事务已读取的数据。
- 在当前事务完成之前,其他事务无法插入其键值落在当前事务中任何语句读取的键范围内的新行。
范围锁放置在与事务中执行的每个语句的搜索条件相匹配的键值范围内。这会阻止其他事务更新或插入符合当前执行的任何语句的任何行。
交易。
....
由于并发量较低,仅在必要时使用此选项.
正如@Bertie 指出的,实体框架是围绕乐观并发模型构建的。使用乐观并发 (OC) 的原因有很多,并且处理不可避免的冲突的模式也有很多。 OC让你变得更高更有趣。对所有事情使用序列化交易会让你像《12只猴子》中的布鲁斯·威利斯一样——在你的软垫房间的地板上塞满了氯磺嗪。你现在不想要这样了,是吗?
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)