2016-03-20 27 views
0

エンティティフレームワークを広範囲に使用するプロジェクトがあります。そして、それはすべて正常に動作します。エンティティフレームワークが既存の関連エンティティを更新しない

ただし、作成しようとしている更新が1つあり、更新もエラーもスローされません。

基本的なプロセスは、既存のエンティティを使用して、新しいエンティティ(異なるタイプ)を作成することです。新しいエンティティはきれいに保存しますが、既存のエンティティは保存しません。

通常、これが発生した場合、エンティティがコンテキストにアタッチされていないことを意味します。しかし、それがあり、私はそれを「追加」するだけでなく、再び付けてみましたが、私は運がなかったのです。

 if (fileRowEntity != null) 
     { 
      this.Context.FileRowEntities.Attach(fileRowEntity); 
      fileRowEntity.FileRowStatusId = (int)FileRowStatus.Converted; 
      fileRowEntity.EdiDocument = ediDocument; 
     } 

     ediDocument.InsertedDate = DateTime.Now; 
     ediDocument.EdiDocumentGuid = Guid.NewGuid(); 
     ediDocument.DocumentMetatdata = null; 
     this.Context.EdiDocuments.Add(ediDocument); 
     var count = this.Context.SaveChanges(); 

ediDocument

が保存されますが、 fileRowEntityは保存されません。

私はこのことを理解しようとしている私の髪を裂いています。私は明示的な第二のfileRowEntityを節約しようとしたが、それは戻って保存されたゼロの変更が付属しています:

 if (fileRowEntity != null) 
     { 
      fileRowEntity.EdiDocumentId = ediDocument.EdiDocumentId; 
      fileRowEntity.Column100 = "X"; 
      this.Context.FileRowEntities.Attach(fileRowEntity); 
      count = this.Context.SaveChanges(); 
     } 

countは常にゼロであり、データベースが更新されません。

これをデバッグしようとすると、他に何か分かりません。

+0

エンティティをアタッチしても、変更されたとマークされません。Context.Entry(fileRowEntity).State = EntityState.Modified;を試しましたか? (それを添付する必要はありません。エンティティがデタッチされている場合は、エンティティを添付します)。エンティティがプロキシであるか、あらかじめ読み込まれていない限り、EFはあなたが指示しない限り、変更があったことを認識しないため、更新は行われません。それを明示的に 'Modified'とするとうまくいくはずです。 – Jcl

+0

ありがとうございます。はい、それは確かに保存作業を行います。これは、エンティティが実際に同じコンテキストにないことを意味しますか?私が知る限り、同じエンティティマネージャを使用してエンティティを取得し、エンティティを保存します。 –

+0

エンティティがデータベースからロードされると、元の値(取得されたもの)はコンテキストに格納されます(実際には 'Context.Entry(エンティティ).OriginalValues'でチェックできます)。 (DetectChangesを呼び出すことによって)変更すると、新しい値が格納され(Context.Entry(Entity).CurrentValuesでチェックすることができます)、変更された値があれば、変更を保存するときに 'UPDATE'が生成されます。したがって、元のエンティティが同じコンテキストでデータベースから取得された場合は、変更を検出して変更内容を保存する必要があります。 – Jcl

答えて

2

エンティティをコンテキストにアタッチしても、変更されたものとしてマークされません。あなたのケースでは

、推定は、あなたが上SaveChanges()を呼び出しているコンテキストインスタンスということです、それはそれが変更されたこと(または変更されたもの)を知らないので、fileRowEntityオブジェクトを取得したことと同じではありません。

DbContextがストアからオブジェクトを取得する場合、それはその元の値(あなたがそのクエリにAsNoTracking()を使用しない場合)のコピーを保存し、それはあなたが明示的に行うことができますDetectChanges()への呼び出しによって変更を検出するたびに、しかし、通常のDbContext実装は多くの点でそれを単独で呼び出します)、新しいオブジェクト値が格納されます。それらの間に相違がある場合、SaveChangesへの次の呼び出しは、ストア/データベース内のエンティティを更新します。

エンティティだったEFを教えてくださいContext.Entry(fileRowEntity).State = EntityState.Modified;を使用して:あなたは修正されたエンティティをマーク明示することができますので、それは何も知りません

あなたはエンティティを添付するが、変更としてそれをマークしていない、変更されましたエンティティ全体に対してSaveChanges()を呼び出すと、更新コマンドが生成されます(UPDATE SQLのすべてのフィールド値が送信されます)。これを行うと、エンティティがコンテキストにアタッチされていない場合でもエンティティがアタッチされます(アタッチして状態を設定する必要はありません)。

変更されたプロパティ(またはエンティティOriginalValues)のみをマークすることもできます。これにより、クエリが最適化されます(実際に変更されたフィールドのみが更新されます)。これらの変更を自分で追跡するのはちょっと面倒ですが、追加の最適化が必要な場合は、一発の価値があります(個人的にはデータベースサーバーに重大な負荷がかからず、すべてのビットがカウントされない限り、

1

上記の行動のための第二の理由があります:私は、これはコンストラクタで設定し、それを削除し、期待通りにすべての仕事をしていたた後

Context.Configuration.AutoDetectChangesEnabled = false; 

:このコードは、変更の追跡をオフにします。

+1

そうです。デフォルトは自動で、私はあなたがそれを無効にできた可能性は考えていませんでした。自動変更検出を有効にした後で動作が遅い場合は、DetectChangesを明示的に呼び出すことができます。 EFは必要以上に多くの検出を行う傾向があります:-) – Jcl

+0

良い点。もう一度、ありがとう、私はこれを把握できませんでした:) –

関連する問題