如何使用 Entity Framework 在一笔交易中更新选定的记录?
How to update selected records in one transaction with Entity Framework?
我正在使用 SQL 服务器。我的情况如下所示:
- 我有一个table
Messages
。 table 有一列 MessageStatusId
- 我有几个可以访问这个数据库的服务
- 每个服务 select 定期发送状态为
New
的消息并以某种方式处理这些消息
- 服务 select 消息如下:
await DbContext.Set<Message>()
.Where(m => m.MessageStatusId == MessageStatusEnum.New)
.ToListAsync();
- 处理后,服务更新消息状态
我不希望服务 select 同一组记录。所以我需要将消息状态更新为 InProcess
。如何通过 Entity Framework?
在一笔交易中实现这一点
您可以实施悲观锁定以确保一次只有一个工作人员访问 table,但是保持 table 访问尽可能短以避免之间的死锁非常重要客户。我建议每个请求获取有限数量的行:
var options = new TransactionOptions
{
IsolationLevel = System.Transactions.IsolationLevel.Serializable,
Timeout = new TimeSpan(0, 0, 0, 10)
};
var messageIds = new List<int>();
using(var scope = new TransactionScope(TransactionScopeOption.RequiresNew, options))
{
using (var context = new MessageDbContext())
{
var messages = context.Messages
.Where(x => x.MessageStatusId == MessageStatusEnum.New)
.OrderBy(x => x.MessageDate)
.Take(100)
.ToList();
foreach(var message in messages)
message.MessageStatusId = MessageStatusEnum.InProgress;
context.SaveChanges();
messageIds = messages.Select(x => x.MessageId).ToList();
}
scope.Commit();
}
我的建议是:
- 将此 Message 实体分离到一个有界 DbContext 中,该 DbContext 仅服务于消息 checking/status 更新,没有其他。此消息实体可以只是此操作的 MessageId 和 MessageStatusId,以及其他检查消息状态/w 悲观锁定的实体。
- 使用同步调用,比异步调用更快。
- 获取行,将它们标记为正在进行并获取它们的 ID,然后提交状态更改。之后你可以用乐观锁阅读它们,在你有空的时候处理,避免死锁。
- 限制查询的行数以避免在碰巧有大量积压时出现意外。 (10, 100, 取其合理)
我正在使用 SQL 服务器。我的情况如下所示:
- 我有一个table
Messages
。 table 有一列MessageStatusId
- 我有几个可以访问这个数据库的服务
- 每个服务 select 定期发送状态为
New
的消息并以某种方式处理这些消息 - 服务 select 消息如下:
await DbContext.Set<Message>() .Where(m => m.MessageStatusId == MessageStatusEnum.New) .ToListAsync();
- 处理后,服务更新消息状态
我不希望服务 select 同一组记录。所以我需要将消息状态更新为 InProcess
。如何通过 Entity Framework?
您可以实施悲观锁定以确保一次只有一个工作人员访问 table,但是保持 table 访问尽可能短以避免之间的死锁非常重要客户。我建议每个请求获取有限数量的行:
var options = new TransactionOptions
{
IsolationLevel = System.Transactions.IsolationLevel.Serializable,
Timeout = new TimeSpan(0, 0, 0, 10)
};
var messageIds = new List<int>();
using(var scope = new TransactionScope(TransactionScopeOption.RequiresNew, options))
{
using (var context = new MessageDbContext())
{
var messages = context.Messages
.Where(x => x.MessageStatusId == MessageStatusEnum.New)
.OrderBy(x => x.MessageDate)
.Take(100)
.ToList();
foreach(var message in messages)
message.MessageStatusId = MessageStatusEnum.InProgress;
context.SaveChanges();
messageIds = messages.Select(x => x.MessageId).ToList();
}
scope.Commit();
}
我的建议是:
- 将此 Message 实体分离到一个有界 DbContext 中,该 DbContext 仅服务于消息 checking/status 更新,没有其他。此消息实体可以只是此操作的 MessageId 和 MessageStatusId,以及其他检查消息状态/w 悲观锁定的实体。
- 使用同步调用,比异步调用更快。
- 获取行,将它们标记为正在进行并获取它们的 ID,然后提交状态更改。之后你可以用乐观锁阅读它们,在你有空的时候处理,避免死锁。
- 限制查询的行数以避免在碰巧有大量积压时出现意外。 (10, 100, 取其合理)