3

プロジェクト内のすべての変更されたレコードと削除されたレコードを維持し、[ステータス] 列を使用してそれらのステータスを追跡したいと考えています。OriginalValues.ToObject()以下は私の最初の試みのコードですが、明らかな理由で DbEntityEntry にキャストできないようです。これを達成するにはどうすればよいですか?

    public override int SaveChanges()
    {
        var now = DateTime.Now;
        var currentUser = HttpContext.Current.User.Identity.Name;
        var trackedEntities = ChangeTracker.Entries<ITrackable>();

        foreach (var trackedEntity in trackedEntities)
        {
            switch(trackedEntity.State)
            {
                case System.Data.EntityState.Added:
                    trackedEntity.Entity.CreatedDate = now;                        
                    trackedEntity.Entity.CreatedBy = currentUser;                        
                    trackedEntity.Entity.Status = Status.Active;
                    break;
                case System.Data.EntityState.Modified:                        
                    var originalEntity = trackedEntity.OriginalValues.ToObject() as DbEntityEntry<ITrackable>;                        
                    originalEntity.Entity.ModifiedDate = now;
                    originalEntity.Entity.ModifiedBy = currentUser;
                    originalEntity.Entity.Status = Status.Modified;

                    var newEntity = trackedEntity.CurrentValues.ToObject() as DbEntityEntry<ITrackable>;
                    newEntity.State = System.Data.EntityState.Added;
                    newEntity.Entity.Status = Status.Active;                                                
                    break;
                case System.Data.EntityState.Deleted:
                    trackedEntity.State = System.Data.EntityState.Modified;
                    trackedEntity.Entity.Status = Status.Deleted;
                    break;                            
            }                
        }
        return base.SaveChanges();
    }
4

3 に答える 3

2

あなたがこの事件で何を達成しようとしているのかを正しく理解しているかどうかはわかりませんModified。しかし、私の理解では、完全に新しいオブジェクトを作成し、ディクショナリToObject()のプロパティ値で埋めます。OriginalValuesしたがって、originalEntityコンテキストにアタッチされておらず、変数がスコープ外になったときに何の影響もなくガベージコレクションされます。

したがって、originalEntity変更を保存する前に、最後のバージョンを保存するために、を新しく追加したエンティティとしてデータベースに保存する必要はありませんか?

私はこれを試してみます:

case System.Data.EntityState.Modified:                        
    var originalEntity = trackedEntity.OriginalValues.ToObject() as ITrackable;
    originalEntity.ModifiedDate = now;
    originalEntity.ModifiedBy = currentUser;
    originalEntity.Status = Status.Modified;
    Entry(originalEntity).Status = System.Data.EntityState.Added;

    trackedEntity.Entity.Status = Status.Active;
    break;

trackedEntityModified状態にあるため、とにかくoriginalEntity保存され、変更前の状態を表す新しいオブジェクトとして作成および保存されます。

辞書で表されるタイプのオブジェクトを作成するため、キャストがITrackable機能するはずです。これは、このインターフェイスで列挙をフィルタリングするためである必要があります。ToObject()OriginalValuesITrackableChangeTracker.Entries

上記はテストされていません、私はそれがうまくいくかどうかわかりません。

編集

originalEntityはモデル内のエンティティであり、はであるため、上記の名前は少しわかりにくいtrackedEntityですDbEntityEntry<T>。たぶんそれをoriginalEntityObject(醜い)またはより良い名前に変更しますtrackedEntityEntry

ChangeTracker.DetectChanges()言及するだけです:ループに入る前に呼び出すことが絶対に必要です(結果的に変更追跡プロキシを使用している場合を除く)foreach。そうしないと、エントリが正しい最終状態になく、間違ったcaseセクションを入力するか、セクションをまったく入力しないためです(状態はUnchanged変更されていますが、プロパティは変更されています)。POCOの変更は、のスナップショットとの比較によって検出されます。OriginalValuesこの最後の比較はbase.SaveChanges、ループので、遅すぎます。(ここでの回答の「編集2」も参照してください:https ://stackoverflow.com/a/6157071/270591 。)

于 2012-05-08T17:48:35.487 に答える
2

同様の目標を実装するために SaveChanges() をオーバーライドする方法を探していました

このようにキャストする方が簡単です。

((ITrackable)trackedEntity.Entity).CreatedDate = now;
于 2012-12-11T16:08:39.020 に答える
0

使用している方法論と同じではありませんが、これにはリポジトリ パターンを使用します。アプリの残りの部分は、リポジトリ クラスをインスタンス化し、呼び出しSave(objToSave)などを行うだけDelete(objToDelete)です。これで、実行プロセスは実際のデータ ストアから切断され、適切なアクションを実行できます。たとえば、 を更新したりModifyDate、 を変更したりします。アプリケーションの残りの部分に をStatus公開している場合DataContext、内部で詳細を制御するのは非常に困難です。 .

于 2012-05-08T17:58:36.143 に答える