0

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

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 的数据库中,因为现有的检查都不会返回一行。我已经大大简化了这个示例,因为在我的真实示例中,当我从服务中获取“图像”时存在时间问题。

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

如果我正确理解 EF,我可以通过创建ExternalId一个主键然后使用并发来处理这个问题,对吧?有什么方法可以避免更改我当前的模型,还是这是唯一的选择?

4

1 回答 1

1

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

于 2012-12-23T23:02:40.497 回答