1

我正在尝试了解实体框架的工作原理。我了解 EF SaveChanges 基本上是围绕事务更新的包装器。我还了解到,如有必要,您可以将两个上下文包装在 TransactionScope 中。

我正在使用代码优先方法。

我不明白的是我将如何进行更新

UPDATE Inventory SET Available = Available - 1 WHERE Available > 0

换句话说 - 我如何确保在进行更新之前至少有 X 个可用库存?

我想我可以编写代码来查看产品的库存并验证是否有足够的库存来完成购买:

if (Product.Inventory - quantityToPurchase < 0) throw new Exception(..)

但是,如果两个客户试图同时购买,并且从数据库中为每个客户获取的对象声称有 2 件物品在库存中,那该怎么办?我上面的逻辑不会明白这一点。

如何确保 SaveChanges() 方法仅在 IF 和 ONLY IF(Available - quantity)大于 0 时提交对对象的更改?

4

2 回答 2

1

当您通过覆盖 SaveChanges 方法保存实体时,您需要执行此检查:

public override int SaveChanges()
{
    var entities = ChangeTracker.Entries()
                                .Where(e => e.State == EntityState.Added || 
                                            e.State == EntityState.Modified)
                                .Select(e => e.Entity())
                                .OfType<YourEntityType();

    foreach (var entity in entities)
    {
        // Run business rule
    }

    return base.SaveChanges();
}
于 2012-06-25T17:45:45.717 回答
1

实体框架默认使用乐观并发。我在原始帖子中描述的内容称为 EF 中的悲观并发。有两个属性可用于实现此目的。

首先是Timestamprowversion在表中创建一列。EF 将自动检测到这一点,并始终where在更新中添加一个子句,将实体中的属性值与数据库中列的值进行比较。update只有当两者匹配时,该语句才会成功。该rowversion列由服务器自动递增。这可确保您始终更新内存中(在 POCO 中)中的相同数据。如果其他人在您获取该行之后并且在您更新它之前更改了该行,则更新将失败。

其次是ConcurrencyCheckTimestamp. 它将导致 POCO 属性的值包含在where子句中。最大的不同是它不会像遗嘱那样更新此列rowversion

于 2012-06-30T03:26:40.757 回答