1

これが私がEFを使用している状況です。

  1. リポジトリは A のインスタンスを取得し、プレゼンテーション層 (つまり、MVC コントローラー) に戻ります。

  2. コントローラーは、A のインスタンスの特定のプロパティを変更し、与えられたインスタンスを永続化します。

  3. 永続化する前に、オブジェクトに対して行われた変更を把握し、変更が許可されているかどうかを検証する必要があります。

  4. 変更を比較するには、データベースの古いインスタンスが必要です。

  5. しかし、EF は同じ汚れたインスタンスを返すため、それらを比較することはできません。

私がやってみたこと:クラス構造

public Class A {
 public B B {get;set;}
}

public class B {
  public ICollection<A> As {get;set;}
  public C c { get; set;}
}
public class C {
}

B と C は同じデータベース テーブルにマップされます。

  1. これは、EF が古いインスタンスを追跡しており、そのインスタンスで save がまだ呼び出されていないためです。そのため、同じ inatce が返されます。

  2. そのため、遅延読み込みとプロキシ生成をオフにし、オブジェクトをリポジトリの追跡不可として返しました。

  3. EF は DB から新しいレコードを返しますが、A のプロパティを変更すると、B の A のコレクションで、コレクション全体ではなく、変更した A のインスタンスのみが読み込まれます。

  4. 新しい A を作成して保存する場合は、次のようにします

    B b = GetSomeOldB(); A a = 新しい A(); aB = b a.Save();

  5. したがって、基本的には新しい A をコンテキストに追加し、SaveChanges を呼び出します。

  6. Ef は、「C を B にキャストできません」という例外を返します。

基本的に、私が望むのは、コンテキストから古いオブジェクト グラフを取得することだけです。

本当に助けていただければ幸いです!!

最終的に実装されたソリューションは次のとおりです。 1. 追跡とプロキシの作成を元に戻します。 2. EF から元のコピーを取得します。3.エンティティの新しいインスタンスをハイドレートするために、この一般的なメソッドを作成しました

public ICollection<T> GetOriginalCollection<T>(ICollection<T> changedCollection) where T : class {
      ICollection<T> original = new Collection<T>();
      foreach (var item in changedCollection) {
          //Dont return the newly added ones to the original collection
          if (_context.Entry(item).State != EntityState.Added){
              original.Add(GetOriginal(item));
          }
      }
      return original;
  }

public T GetOriginal<T>(T changedEntity) where T : class {
      Func<DbPropertyValues, Type, object> getOriginal = null;
      getOriginal = (originalValues, type) =>
      {
          object original = Activator.CreateInstance(type, true);
          foreach (var ptyName in originalValues.PropertyNames) {
              var property = type.GetProperty(ptyName);
              object value = originalValues[ptyName];
              //nested complex object
              if (value is DbPropertyValues) { 
                  property.SetValue(original, getOriginal(value as DbPropertyValues, property.PropertyType));
              } else{
                  property.SetValue(original, value);
              }
          }
          return original;
      };
      return (T)getOriginal(_context.Entry(changedEntity).OriginalValues, typeof(T));
  }
4

1 に答える 1