2016-10-18 7 views
0

私はEF 6.0を少し新しくしていますので、ここで何か間違っていると思います。 エンティティフレームワークM:1の関係でプライマリキーが複製される

  1. は、私がここで間違って何をやっている問題に関連する2つの質問があります
  2. は何のベストプラクティスをだ私は、コード最初のモデルを使用しています。この

を達成し、EDMXを使用するには設計者はモデルと関係を設計するために、システムはウェブサービスから情報を定期的に取り出し、デスクトップアプリケーションのローカルデータベース(SQL Lite)に保存する必要があります。

enter image description here

ので、私は移入してチケットを保存しようとするとTicketSeatTypeを挿入しようとしたとき、私は重複キーの例外を取得し、APIからのオーダーリストを取得する -

ように私は、dbContextへの切符を挿入しない方法TicketSeatTypeとTicketPriceTypeの挿入を再試行しませんが、子オブジェクトの状態を変更しないで設定しようとしましたが、挿入されているようです

2番目に、EFを使用してこれを達成するにはどうすればよいでしょうか?各オブジェクトをメモリに読み込んで比較するのは非常に非効率的です。

私はリストを定期的に更新する必要があるため、データベース内の各オブジェクトをチェックしてから更新しなければなりません。

コード:

//read session from db 
       if (logger.IsDebugEnabled) logger.Debug("reading session from db"); 
       dbSession = dbContext.SessionSet.Where(x => x.Id == sessionId).FirstOrDefault(); 

       //populate orders 
       List<Order> orders = (from e in ordersList 
             select new Order { 
              Id = e.OrderId, 
              CallCentreNotes = e.CallCentreNotes, 
              DoorEntryCount = e.DoorEntryCount, 
              DoorEntryTime = e.DoorEntryTime, 
              OrderDate = e.OrderDate, 
              SpecialInstructions = e.SpecialInstructions, 
              TotalValue = e.TotalValue, 
              //populate parent refernece 
              Session = dbSession 
             }).ToList(); 

       //check and save order 
       foreach (var o in orders) { 
        dbOrder = dbContext.OrderSet.Where(x => x.Id == o.Id).FirstOrDefault(); 
        if (dbOrder != null) { 
         dbContext.Entry(dbOrder).CurrentValues.SetValues(o); 
         dbContext.Entry(dbOrder).State = EntityState.Modified; 
        } 
        else { 
         dbContext.OrderSet.Add(o); 
         dbContext.Entry(o.Session).State = EntityState.Unchanged; 
        } 
       } 
       dbContext.SaveChanges(); 

       //check and add ticket seat type 
       foreach (var o in ordersList) { 
        foreach (var t in o.Tickets) { 
         var ticketSeatType = new TicketSeatType { 
          Id = t.TicketSeatType.TicketSeatTypeId, 
          Description = t.TicketSeatType.Description 
         }; 
         dbTicketSeatType = dbContext.TicketSeatTypeSet.Where(x => x.Id == ticketSeatType.Id).FirstOrDefault(); 
         if (dbTicketSeatType != null) { 
          dbContext.Entry(dbTicketSeatType).CurrentValues.SetValues(ticketSeatType); 
          dbContext.Entry(dbTicketSeatType).State = EntityState.Modified; 
         } 
         else { 
          if (!dbContext.ChangeTracker.Entries<TicketSeatType>().Any(x => x.Entity.Id == ticketSeatType.Id)) { 
           dbContext.TicketSeatTypeSet.Add(ticketSeatType); 
          } 
         } 
        } 
       } 
       dbContext.SaveChanges(); 

       //check and add ticket price type 
       foreach (var o in ordersList) { 
        foreach (var t in o.Tickets) { 
         var ticketPriceType = new TicketPriceType { 
          Id = t.TicketPriceType.TicketPriceTypeId, 
          SeatCount = t.TicketPriceType.SeatCount, 
          Description = t.TicketPriceType.Description 
         }; 
         dbTicketPriceType = dbContext.TicketPriceTypeSet.Where(x => x.Id == ticketPriceType.Id).FirstOrDefault(); 
         if (dbTicketPriceType != null) { 
          dbContext.Entry(dbTicketPriceType).CurrentValues.SetValues(ticketPriceType); 
          dbContext.Entry(dbTicketPriceType).State = EntityState.Modified; 
         } 
         else { 
          if (!dbContext.ChangeTracker.Entries<TicketPriceType>().Any(x => x.Entity.Id == ticketPriceType.Id)) { 
           dbContext.TicketPriceTypeSet.Add(ticketPriceType); 
          } 
         } 
        } 
       } 
       dbContext.SaveChanges(); 

       //check and add tickets 
       foreach (var o in ordersList) { 
        dbOrder = dbContext.OrderSet.Where(x => x.Id == o.OrderId).FirstOrDefault(); 
        foreach (var t in o.Tickets) { 
         var ticket = new Ticket { 
          Id = t.TicketId, 
          Quantity = t.Quantity, 
          TicketPrice = t.TicketPrice, 
          TicketPriceType = new TicketPriceType { 
           Id = t.TicketPriceType.TicketPriceTypeId, 
           Description = t.TicketPriceType.Description, 
           SeatCount = t.TicketPriceType.SeatCount, 
          }, 
          TicketSeatType = new TicketSeatType { 
           Id = t.TicketSeatType.TicketSeatTypeId, 
           Description = t.TicketSeatType.Description 
          }, 
          Order = dbOrder 
         }; 
         //check from db 
         dbTicket = dbContext.TicketSet.Where(x => x.Id == t.TicketId).FirstOrDefault(); 
         dbTicketSeatType = dbContext.TicketSeatTypeSet.Where(x => x.Id == t.TicketSeatType.TicketSeatTypeId).FirstOrDefault(); 
         dbTicketPriceType = dbContext.TicketPriceTypeSet.Where(x => x.Id == t.TicketPriceType.TicketPriceTypeId).FirstOrDefault();        

         if (dbTicket != null) { 
          dbContext.Entry(dbTicket).CurrentValues.SetValues(t); 
          dbContext.Entry(dbTicket).State = EntityState.Modified; 
          dbContext.Entry(dbTicket.Order).State = EntityState.Unchanged; 
          dbContext.Entry(dbTicketSeatType).State = EntityState.Unchanged; 
          dbContext.Entry(dbTicketPriceType).State = EntityState.Unchanged; 

         } 
         else { 
          dbContext.TicketSet.Add(ticket); 
          dbContext.Entry(ticket.Order).State = EntityState.Unchanged; 
          dbContext.Entry(ticket.TicketSeatType).State = EntityState.Unchanged; 
          dbContext.Entry(ticket.TicketPriceType).State = EntityState.Unchanged; 
         } 
        } 
       } 
       dbContext.SaveChanges(); 

UPDATE:

は答えを見つけ、それは私がTicketPriceTypeためのリストから新しいエンティティタイプを作成して、上記のコードでは、EFは、オブジェクトへの参照を追跡する方法に関係していますTicketSe atType:

foreach (var o in ordersList) { 
        dbOrder = dbContext.OrderSet.Where(x => x.Id == o.OrderId).FirstOrDefault(); 
        foreach (var t in o.Tickets) { 
         var ticket = new Ticket { 
          Id = t.TicketId, 
          Quantity = t.Quantity, 
          TicketPrice = t.TicketPrice, 
          TicketPriceType = new TicketPriceType { 
           Id = t.TicketPriceType.TicketPriceTypeId, 
           Description = t.TicketPriceType.Description, 
           SeatCount = t.TicketPriceType.SeatCount, 
          }, 
          TicketSeatType = new TicketSeatType { 
           Id = t.TicketSeatType.TicketSeatTypeId, 
           Description = t.TicketSeatType.Description 
          }, 
          Order = dbOrder 
         }; 
.... 

この場合、EFはどのオブジェクトであったかを知らずに挿入しようとします。

ソリューションは、それが同じエンティティを参照していますし、新しいものに

foreach (var t in o.Tickets) { 

          //check from db 
          dbTicket = dbContext.TicketSet.Where(x => x.Id == t.TicketId).FirstOrDefault(); 
          dbTicketSeatType = dbContext.TicketSeatTypeSet.Where(x => x.Id == t.TicketSeatType.TicketSeatTypeId).FirstOrDefault(); 
          dbTicketPriceType = dbContext.TicketPriceTypeSet.Where(x => x.Id == t.TicketPriceType.TicketPriceTypeId).FirstOrDefault(); 

          var ticket = new Ticket { 
           Id = t.TicketId, 
           Quantity = t.Quantity, 
           TicketPrice = t.TicketPrice, 
           TicketPriceType = dbTicketPriceType, 
           TicketSeatType = dbTicketSeatType, 
           Order = dbOrder 
          }; 
...} 
+0

EFエンティティの参照トラッキングに関する詳細はこちら:http://stackoverflow.com/questions/14697661/how-does-entity-framework-decide-whether-to-reference-an-existing-object-or-crea – Danish

答えて

1

を追加しないように、データベースからエンティティを読み、それらを割り当てることであるあなたが書くしようとしていることを考えてはいけません各エンティティの状態を定義するための非常によく似たコードですか? これらの操作はすべて1つのコマンドで処理できます。

エンティティフレームワークコードファーストの新しくリリースされたEntityGraphOperationsで簡単にこれを達成できます。私はこの製品の著者です。そしてgithubcode-projectにはステップバイステップのデモンストレーションが含まれており、サンプルプロジェクトはダウンロード可能です)nugetに掲載しました。 InsertOrUpdateGraphメソッドを使用すると、エンティティは自動的にAddedまたはModifiedに設定されます。 DeleteMissingEntitiesメソッドの助けを借りて、データベースに存在するが現在のコレクションに存在しないエンティティを削除することができます。

// This will set the state of the main entity and all of it's navigational 
// properties as `Added` or `Modified`. 
context.InsertOrUpdateGraph(ticket); 

ところで、私はこれが最も効率的な方法ではないと言及する必要があると感じています。一般的な考え方は、データベースから目的のエンティティを取得し、エンティティの状態を定義することです。それは可能な限り効率的です。

+0

フレームワーク参照のおかげで、私は間違いなくそれを調べます - 私はまだ知識のために興味がありますが、標準のEFを使ってこのシナリオを実装するにはどうすればいいですか - 私は主要な重複キー例外 – Danish

関連する問題