如何在实体框架、禁用延迟加载、禁用代理和实体不可跟踪的情况下保存对象图

本文关键字:实体 跟踪 对象图 保存 情况下 延迟加载 框架 代理 | 更新日期: 2023-09-27 18:35:42

这是我使用 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 从数据库返回新记录,但如果更改了 A 上的某些属性,则在 B 的 A 集合中,它仅加载我更改的 A 实例,而不是整个集合。

  4. 当我想创建一个新的 A 并保存时,我会执行以下操作

    B b = GetSomeOldB();A a = 新的 A();a.B = ba.保存();

  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));
  }

如何在实体框架、禁用延迟加载、禁用代理和实体不可跟踪的情况下保存对象图

我认为

你想要的是在一个断开连接的环境中工作。您可以附加断开连接的实体,并通过指定其实体状态来提供图形中的更改内容。如果你愿意,你可以创建像IObjectState这样的接口,并在你的模型中实现,以找出图中的确切变化。