2016-12-06 60 views
1

我有一个Tag模型在我的应用程序:任何方式使EntityFramework的SaveChanges()方法跳过一个条目,如果它已经存在?

public class Tag 
{ 
    public Tag() { } 
    public Tag(string t) 
    { 
     Name = t; 
     Pictures = new List<Picture>(); 
    } 

    public int Id { get; set; } 
    [MaxLength(96), Index(IsUnique = true)] 
    public string Name { get; set; } 

    public virtual List<Picture> Pictures { get; set; } 

} 

有没有办法告诉框架做ON DUPLICATE DO NOTHING,当具有相同Name的记录已经存在?这总是抛出一个重复的异常,我希望它忽略它并继续前进。

编辑:我已经改变在许多线程EF代码这样:

async Task SaveQueue() 
{ 
    for (;;) 
    { 
     try 
     { 
      await Task.Delay(7500); 
      dbUploadProgress.Visibility = Visibility.Visible; 
      dbUploadProgress.Value = 0; 
      var q = new ObservableCollection<Picture>(manager.Queue.ToList().AsEnumerable()); 
      manager.Queue.Clear(); 
      var imgcount = q.Count(); 
      for (int i = 0; i < imgcount; i++) 
      { 
       using (var pc = new PicsContext()) 
       { 
        var tags = q[i].GetTags(); 
        pc.Sites.Attach(q[i].Site); // I'm actually not sure how to use this. 
        var curUrl = q[i].Url; 
        if (pc.Pictures.FirstOrDefault(o => o.Url == curUrl) != null) 
         continue; 
        foreach (var t in tags) 
        { 
         var tag = pc.Tags.Where(o => o.Name == t).FirstOrDefault(); 
         if (tag == null) 
         { 
          tag = new ViewModel.Tag(t); 
         } 
         q[i].Tags.Add(tag); 
         try 
         { 
          await pc.SaveChangesAsync(); 
         } 
         catch { } 
        } 
        pc.Pictures.Add(q[i]); 
        try 
        { 
         await pc.SaveChangesAsync(); 
        } 
        catch { } 
        dbUploadProgress.Value = (i + 1)/(double)imgcount; 
       } 
      } 
      q.Clear(); 
      MainWindow.AddLog(string.Format("Saved {0} pictures.", imgcount)); 
      dbUploadProgress.Visibility = Visibility.Collapsed; 
      await Task.Delay(1500); 
     } 
     catch { } 
     if (isStopped) 
      break; 
    } 
} 

的问题依然存在,虽然。

回答

1

为什么不运行dbContext.Get.Any(x => x.Name == tag.Name)并跳过基于它的新标签?

我认为问题在于你的队列处理消息异步,所以你可以让2个线程试图插入相同的标记,因为在插入之前检查是否存在逻辑运行。

您可以通过一次只处理1个队列消息(有一个工作/线程处理队列)来解决问题。

或者另一个解决办法可能是隔离保存在try catch中的标签,并正确处理重复的异常(从db重新加载标签,并将其设置在新对象上时使用该标签)。

+0

我正在使用 var tag = pc.Tags.Where(o => o.Name == t).FirstOrDefault(); if(tag == null) {tag = new ViewModel.Tag(t); } q [i] .Tags.Add(tag); 但它似乎不够,因为许多任务一次运行不同的线程。它变得混乱。 – Reynevan

+0

实体上下文不是线程安全的,我假设你为每个线程使用不同的上下文,并从这里出问题。 –

+0

我更改了代码。你可以看看吗?我编辑了原文。 – Reynevan

相关问题