2016-07-08 9 views
4

多対1の関係で、子オブジェクトの1つを削除し、オーバーライドされたSaveChangesで監査証跡を保持しようとしています。SaveChangesをオーバーライドしてEFリレーションシップを削除するとnullが発生する

file.Entity.ProductがEntityState.ModifiedまたはEntityState.Addedを実行しているときに、.Deleted EFを実行しているときに、base.Savechanges()が呼び出される前でも積極的にエンティティからの関係を削除しているようです。

ファイル(子)に対して.Removeを呼び出した後に、このファイルがSaveChangesのオーバーライドに関連付けられたときに取得する方法はありますか?

class File { 
    ... 
    private Product product; 
    private Product lastProduct; 

    public Product Product { 
     get { return product; } 
     set { 
      if (product == value) return; 
      lastProduct = Product; 
      product = value; 
     } 
    } 

    [NotMapped] 
    public Product LastProduct { 
     get { return lastProduct; } 
    } 
    ... 
} 
+0

'file'の値を割り当てる' files'に 'foreach'ループがあると思いますよね? – Shago

+0

流体マッピング – user5135401

答えて

0

あなただけProductプロパティのためにそれが必要な場合は、その定義上のいくつかのカスタムロジックでそれをキャプチャすることができ

しかし、あなたが誤って削除された場合、いつでも削除されたレコードを返すことができると私の意見ではベストプラクティスであるソフト削除を使用しないでください(IsDeleted = false、権限)

これは、あなたはそれがProductID性質を持っている。すなわちFileは、Product外部キーの関連を持っていると仮定して、その製品を見つけることができます、あなたはChangeTrackerのエントリでファイルを見つけるのと同じように、あなたに

1

私が削除した後、関係船にアクセスする方法がないことだと思う:

var files = from e in ChangeTracker.Entries<SavedFile>() 
        where e.State != EntityState.Unchanged 
        select e; 
if (file.State == EntityState.Deleted) 
      { 
       var text = "File Deleted: " + file.Entity.FriendlyFileName; 
       // file.Entity.Product is null 
       var updatedProduct = new Update { Product = file.Entity.Product, UpdateDateTime = DateTime.Now, UpdateText = text, User = HttpContext.Current.Request.LogonUserIdentity.Name }; 
       Updates.Add(updatedProduct); 
      } 
2

を助けることを願っていますProductナビゲーションプロパティのほかに:それは、EFは、エンティティは、ローカルキャッシュからクエリですいつでも削除するエンティティが表示されないことを行動に期待だ

if (file.State == EntityState.Deleted) 
{ 
    var text = "File Deleted: " + file.Entity.FriendlyFileName; 
    var productEntry = ChangeTracker.Entries<Product>() 
            .FirstOrDefault(p => p.Entity.ID == file.ProductID); 
    if (productEntry != null) 
    { 
     var updatedProduct = new Update { Product = productEntry.Entity, UpdateDateTime = DateTime.Now, UpdateText = text, User = HttpContext.Current.Request.LogonUserIdentity.Name }; 
     Updates.Add(updatedProduct); 
    } 
} 

(例えばDbSet.Local)。そのため、これらのエンティティがナビゲーションプロパティに表示されないように関連付けを解除する必要もあります。ファイルを削除すると、EFはそれをcontext.Files.Localに表示しませんが、product.Filesのようなナビゲーションプロパティには表示されません(また、アソシエーションの相手側でもfile.Productは表示されません)。ゲルト・アーノルドによって提供さ

+0

を使用している場合、必要なフィールドをプロパティに保存し、NotMappedまたはIngnoreにマークすることができます。 – Monah

+0

全くありません。私は 'ChangeTracker.Entries ()'に問い合わせています。 –

+0

下の票がロックされていますので、この回答を編集して投票できるようにしてください – Monah

0

回答は動作するはずです! - それは FirstOrDefaultた(p =>p.Stateをチェックすることは理にかなっているかどうかわからなく=関連するエンティティが変更なしにまだあるかもしれないとして をEntityState.Unchanged状態。

何も動作した場合、がオーバーライドさSaveChangesメソッドでエンティティをリロードしてみてください。

this.Entry((file.Entity as <<Your Entity Type>>)).Reload(); 
//do your operation/audit log 
//then reset the Entity State to Deleted 
this.Entry((file.Entity)).State = EntityState.Deleted; 

編集:だけで

this.Entry(file.Entity as <Type>).Reference(e=> e.Product).Load(); 

または明示的な負荷だけで必要な関連企業は、これがリロード中に余分なデシベルヒットで終わるでしょう。

編集:別のオプションは、他の良いオプションは、監査テーブルを埋めるために、このシナリオでは、生のSQLのINSERTクエリを実行についてはどのように

を発見した場合は、再び?

+0

エンティティの読み込みには、あらゆる種類の副作用があります。変更を保存する際にこれを行うのは良い考えではありません。それが問題でなければ、これは 'SaveChanges'を潜在的に高価な操作にします。 –

+0

@ GertArnold-確かに、削除されたエンティティに対してのみこれを行うことを意味していました。遅延ロードが無効にされ、関連エンティティが熱心に/明示的にロードされていない最悪のシナリオを考えていました。この場合、おそらくdbを押すことが唯一の選択肢です。私が言及したように、答えはうまくいくはずです。あなたの答えを投票しようとしましたが、ここの初心者ではありませんでした。投票にはいくつかのスコアが必要なようです:) – Developer

+0

ChangeTrackerのクエリが失敗するという別のシナリオは、切断されたものです。詳細を取得したコンテキストは、get操作の後に削除された可能性があり、削除操作が実行されると、別のコンテキストになる可能性があります。 context.Entry()を実行した場合はどうなりますか? State = EntityState.Deleted?関連するエンティティ/ナビゲーションプロパティの詳細がチェンジトラッカーにあるとは確信していません。ちょっと声をかけて... – Developer

関連する問題