EF& Parallel.ForEach违反PRIMARY KEY约束

时间:2017-02-02 10:29:36

标签: c# sql-server entity-framework

我有方法AddOrUpdateFruitMetaData,它应该在FruitMetaData表中添加或更新记录。 不幸的是,我不断收到错误:

Violation of PRIMARY KEY constraint 'PK_FruitMetaData'. Cannot insert duplicate key in object 'dbo.FruitMetaData'. The duplicate key value is (0, COLOR). The statement has been terminated.

即使我之前试图找到现有记录,这怎么可能呢?

同时使用AddOrUpdate()而不是System.Data.Entity.Migrations中的Add()对我没有帮助。

调用堆栈看起来:

Parallel.ForEach的主要课程中,多个for循环看起来像这样:

Parallel.ForEach(args)
{
    for(something)
    {
        var fruit = new Fruit();
        fruit.FruitId = uniqueId;
        UpdateOrCreateFruitMetaData(fruit, "Color", "Blue")
    }
}

我正在呼叫方法:

private void UpdateOrCreateFruitMetaData(Fruit fruit, string metaType, string value)
{
    var fruitMetaData = new FruitMetaData();
    fruitMetaData.FruitId = fruit.FruitId;
    fruitMetaData.MetaType = metaType;
    fruitMetaData.Value = value;

    using (var db = Context.DB)
    {
        db.AddOrUpdateFruitMetaData(fruitMetaData);
    }
}

该方法使用Context.DB,它是包含new DBEntity()的对象,也是Dispose()。所以每次都会处理我的实体上下文。

然后我调用下一个方法AddOrUpdateFruitMetaData()

AddOrUpdateFruitMetaData(FruitMetaData fruitMetaData)
{
    lock (thisLock)
    {
        try
        {
            var fmd = db.FruitMetaData.Where(x => x.FruitId  == fruitMetaData.FruitId)
                                      .Where(x => x.MetaType == fruitMetaData.MetaType)
                                      .FirstOrDefault();
            if (fmd == null)
                db.FruitMetaData.Add(fruitMetaData);
            else
                fmd.Value = fruitMetaData.Value;


            db.SaveChanges();
        }
        catch (Exception ex)
        {
            Log.Error($"AddOrUpdateFruitMetaData. FruitId:{fruitMetaData.FruitId} MetaType:{fruitMetaData.MetaType}", ex);
        }
    }
}

[编辑]解释using (var db = Context.DB)

我的Context类包含DbData DB属性,如下所示:

public DbData DB 
{ 
    get { return new DbData(); } 
}

DbData类看起来像这样:

public class DbData : IDisposable
{
    private DBEntity db;

    public DbData()
    {
        db = new FruitDBEntity();
    }

    // This class contains that problematic method
    AddOrUpdateFruitMetaData(FruitMetaData fruitMetaData)(...)
}

因此,每次我获得Context.DB属性时,我实际上都在创建新的实体上下文。

0 个答案:

没有答案
相关问题