2016-12-06 5 views
1

У меня есть Tag модели в моем приложении:Любой способ сделать метод SaveChanges() EntityFramework пропустить запись, если она уже существует?

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 уже существует? Это всегда вызывает исключение Duplicate, и я хотел бы просто игнорировать его и двигаться дальше.

Edit: Я изменил код 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) и пропустить добавление нового тега на его основе?

Я думаю, проблема в том, что ваша очередь обрабатывает сообщения async, поэтому вы можете иметь 2 потока, пытающихся вставить один и тот же тег, потому что проверка, существует ли логика, была выполнена до того, как была вставлена ​​вставка.

Вы можете исправить эту проблему, обработав только одно сообщение очереди за раз (имея один рабочий/поток, обрабатывающий очередь).

Возможно, другая работа может заключаться в том, чтобы изолировать сохраненные теги в попытке поймать и обработать дублирующее исключение должным образом (перезагрузка тега из db и использование его при настройке на новый объект).

+0

Я использую var tag = pc.Tags.Where (o => o.Name == t) .FirstOrDefault(); if (tag == null) { tag = новый ViewModel.Tag (t); } q [i] .Tags.Add (тег); Но, похоже, этого недостаточно, потому что многие задачи запускают разные потоки одновременно. Это запутывает. – Reynevan

+0

контекст сущности не является потокобезопасным, я предполагаю, что вы используете разные контексты для каждого потока и отсюда проблема. –

+0

Я изменил код. Можете ли вы взглянуть на него? Я отредактировал оригинальный пост. – Reynevan

 Смежные вопросы

  • Нет связанных вопросов^_^