处理在异步方案中的非键字段上避免EF中的“重复”行

时间:2012-12-23 18:59:14

标签: entity-framework

我目前有一个这样的对象(简化):

public class Image {
    public int Id { get; set; }

    public int ExternalId { get; set; }
}

现在让我说我有这种方法(主要是伪代码):

public void GetImage(int externalId) {
    var existingImage = db.Images.FirstOrDefault(i => i.ExternalId == externalId);

    if (existingImage != null) {
        return existingImage;
    }

    var newImage = new Image() { ExternalId = externalId };
    db.Images.Attach(newImage);
    db.SaveChanges();

    return newImage;
}

由于ExternalId不是密钥,因此更改跟踪器无需关心跟踪器中是否有“重复”图像。

现在,让我们说这个方法被调用两次,同时通过AJAX和Web API(我当前的场景)。它是异步的,所以现在有两个线程调用这个方法。

如果调用之间的时间足够短(在我的情况下),则将使用相同的外部ID向数据库添加两行,因为现有检查都不会返回一行。我已经大大简化了这个例子,因为在我的实例中,当我从服务中获取“图像”时会出现计时问题。

我该怎样防止这种情况?无论是新的还是更新的,我都需要返回图像。我在数据库中添加了一个Unique Constraint,所以我得到了一个例外,但是在客户端上,调用失败了,而使用现有的图像而不是抛出异常。

如果我正确理解EF,我可以通过使ExternalId成为主键然后使用并发来处理这个来解决这个问题,对吗?有没有办法避免更改我当前的模型或这是唯一的选择?

1 个答案:

答案 0 :(得分:1)

如果您已经拥有定义实体唯一性的属性(ExternalId),则应将其用作密钥,而不是创建另一个未指定实体唯一性的虚拟密钥。如果不使用ExternalId作为键,则必须对数据库中的该列设置唯一约束,并在代码中处理异常以从数据库加载现有Image