EF6 无法插入重复的密钥 - 我找不到此异常的原因



当我尝试使用方法AddTimeSeriesDefinition(TimeSeries series)AddTimeSeriesMetaData(TimeSeriesMetaData tsData)时遇到问题Parallel.ForEach()

为此挣扎了几个小时,我不敢相信我找不到任何解决方案甚至理论原因。

在我的类Data中包含我的数据库上下文DBEntity db = new DBEntity()我有AddTimeSeriesDefinition(TimeSeries series)AddTimeSeriesMetaData()方法:

public class Data : IDisposable 
{
    private DBEntity db;
    public Data()
    {
         db = new DBEntity();
    }      
    public TimeSeries AddTimeSeriesDefinition(TimeSeries series)
    {
        var timeSeries = db.TimeSeries.Where(ts => ts.Key1 == series.Key1 )
                                      .Where(ts => ts.Key2 == series.Key2 )
                                      .Where(ts => ts.Key3 == series.Key3 )
                                      .FirstOrDefault();
        if ( timeSeries == null )
        {
             timeSeries = db.TimeSeries.Add(series);
             db.SaveChanges();
        }
        return timeSeries;
    }
    public void AddTimeSeriesMetaData(TimeSeriesMetaData tsData)
    {
        var tsd = db.TimeSeriesMetaData.Where(ts => ts.Key1 == tsData.Key1 )
                                       .Where(ts => ts.Key2== tsData.Key2)
                                       .FirstOrDefault();
        if (tsd == null)
            db.TimeSeriesMetaData.Add(tsData);
        else
            tsd.Value = tsData.Value;
        try
        {
            db.SaveChanges();
        }
        catch (Exception ex)
        {
            Log.Error($"Error occurred (...) Key1:{tsData.Key1} Key2:{tsData.Key2}", ex);
        }
    }

    Dispose()
    {...}
}

但是,当我在主类中使用它们时,例如:

private MainClass
{
    Data DB { get { value = new Data() } }
    ...
    Parallel.ForEach( // arguments )
    {
        ...
        using( var db = DB ) 
        {
             db.AddTimeSeriesDefinition(timeSeries);  
        } 
        ...
    }
}

有时,完全随机地在排队时崩溃

db.SaveChanges();

例外:

Violation of PRIMARY KEY constraint 'PK_TimeSeriesMetaDatas'. Cannot insert duplicate key in object 'dbo.TimeSeriesMetaData'. The duplicate key value is ("Key1", "Key2"). The statement has been terminated.

例如,我的 TimeSeriesMetaData EF 类:

[Table("TimeSeriesMetaData")]
public partial class TimeSeriesMetaData
{
    [Key]
    [Column(Order = 0)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public string Key1 { get; set; }
    [Key]
    [Column(Order = 1)]
    public string Key2 { get; set; }
    [Required]
    public string Key3 { get; set; }
}

我读过每次为每个操作创建Entity Framework DBContext也应该是线程安全的。如果我总是检查记录是否存在,可能导致此问题的原因是什么?

我将不胜感激任何帮助。

问题是 DbSet 不是 ThreadSafe。您在 Parallel.ForEach 循环中有一个运行条件。您必须锁定对这两种方法的调用。https://msdn.microsoft.com/en-us/library/c5kehkcz.aspx

希望对你有帮助

最新更新