实体框架检索导航属性

本文关键字:属性 导航 检索 框架 实体 | 更新日期: 2023-09-27 17:50:48

我正在使用EF 5,我已经启用了延迟加载。当我从数据库中检索实体时,它可以完美地工作。

这是我的问题。我有一个通用的存储库来执行数据库操作。
    public int Update(T t) //Update method implemented at repository layer
    {
        dbSet.Attach(t);
        context.Entry(t).State = EntityState.Modified;
        return context.SaveChanges();
    }
    public T Update(T t, int id) //This Method calls the above method to
    {
        if (Update(t) > 0)
        {
            //Now entity is updated so retrieve the entity from the database.
            return Get(id); //This line of code doesn't return entity with reference. It does return the updated entity.
        }
        return null;
    }

现在,当我使用主键查询实体以获得更新的实体时,它会给我更新的实体,但没有任何引用属性。我不能在这里使用延迟加载,因为它会抛出一个异常。

更新实体后,我注意到dbSet。Local具有更新后的实体。所以我试图清除之前,我检索更新的实体,但没有运气。我还尝试通过上下文重新加载实体,但它不会重新加载导航属性。我不能使用引用属性,因为我正在使用通用存储库。我能完成的唯一方法是处置并创建context和dbset的新实例。

我想返回已更新的实体,并填充关系属性。有没有人有好的解决办法?

实体框架检索导航属性

我启用了延迟加载

我正在附加POCO实体

我从你的评论中假设,在你的应用程序的某个地方,你正在实例化你的实体,如new MyEntity(),这样的延迟加载将不起作用,因为它不是代理POCO。

考虑到您已经启用了延迟加载,您想要做的最简单的方法是使用代理poco。也就是说,使用下面的代码实例化一个实体,无论它在哪里:

MyEntity entity = MyContext.MyEntities.Create();

延迟加载应该为您工作。如果您不想这样做或这样做不起作用,那么最好的选择是从数据库中提取现有实体(作为动态代理)并从POCO填充。所以在你的仓库更新方法中:

编辑

我应该注意,也可以做到这一点,而不需要往返于数据库。看到评论。

public T Update(T poco)
{
  //get the entity from db
  T proxyPoco = context.Set<T>().Find(id);
  //alternatively just create the proxy, set the id and attach.
  //no db retrieval.
  //T proxyPoco = context.Set<T>.Create();
  //proxyPoco.Id = poco.Id;
  //context.Set<T>.Attach(proxyPoco);
  if(proxyPoco == null) 
  {
    //throw an exception or handle case where the entity is not found.
    //unecessary if using alternative above.
  }
  else 
  {
    //set the proxy poco values using your original poco
    context.Entry<T>(proxyPoco).CurrentValues.SetValues(poco);
  }
  context.SaveChanges();
  return proxyPoco;
}

因为您返回了代理POCO,所以延迟加载应该可以工作。其他不太理想的选项是:

  1. 丢弃上下文并重新获取实体。
  2. 使用反射显式加载实体的引用和集合。

SaveChanges返回一个int。如果您想要恢复实体,请尝试:

public T Update(T t)
{
    dbSet.Attach(t);
    context.Entry(t).State = EntityState.Modified;
    context.SaveChanges();
    return t;
}