2016-12-06 7 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を持つレコードがすでに存在する場合、ありますか?これは常にDuplicate例外をスローし、無視して移動したいと思います。

編集:私はこれまで多くのスレッド間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つのキューメッセージ(キューを処理するワーカー/スレッドを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(タグ); しかし、多くのタスクが一度に異なるスレッドを実行するため、十分ではないようです。それは混乱します。 – Reynevan

+0

エンティティコンテキストはスレッドセーフではありません。私はあなたが各スレッドごとに異なったコンテキストを使用していると仮定します。 –

+0

私はコードを変更しました。あなたはそれを見てみることができますか?私は元の投稿を編集しました。 – Reynevan

関連する問題