1

这是我使用 EF 的情况。

  1. Repository 获取 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 从数据库返回新记录,但是如果更改了 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

2

我认为您想要的是在断开连接的环境中工作。您可以附加断开连接的实体并通过指定其 EntityState 来提供图中的更改内容。如果您愿意,您可以创建 IObjectState 之类的接口并在您的模型中实现以找出图中的确切变化。

于 2013-10-16T04:46:57.250 回答