2013-01-06 36 views
2

我正在使用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; 
    } 

现在,当我查询实体使用主键来获得更新的实体,它给了我更新的实体,但是没有任何参考性。我不能在这里使用懒加载,因为它会引发异常。

更新enttity后,我注意到dbSet.Local有更新的实体。所以我试图清除之前我检索更新的实体,但没有运气。我也尝试通过上下文重新加载实体,但不重新加载导航属性。我无法使用引用属性作为我使用的通用存储库。 我可以完成的唯一方法是处理并创建上下文和dbset的新实例。

我想返回填充了关系属性的更新实体。有没有人有一个好的解决方案。

+0

有什么异常? – 2013-01-06 23:34:14

+0

它不会抛出异常。所有关联的属性都是空的。 –

+0

你说,因为它抛出一个异常,你不能使用延迟加载。 – 2013-01-14 02:42:50

回答

1

我懒加载启用

我附上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. 使用反射显式加载该实体的引用和集合。
+0

如何填写更新后的值?我使用的是泛型类,所以我无法访问属性。目前我使用第二种方法。我重新创建新的上下文。我想有一个更好的解决方案。 –

+0

@JigarPatel我越看越你的问题,我就越变得困惑。为什么你甚至需要检索实体?据推测,你已经有了一个实体的参考,因为你将它传递给你的更新方法。也许你需要在你的问题中包含进一步的细节。 – 2013-01-16 10:13:54

+0

@JigarPatel'我如何填写更新后的值?'。您必须在运行更新方法之前的某个阶段在实体上设置值,否则您没有理由附加和保存更改。 – 2013-01-16 10:30:04

1

SaveChanges返回int。您希望实体回来,试试这个:

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

这不会返回参考/导航属性。在更新期间,引用属性为空,所以它不会被更新。但是,即使我尝试从数据库中再次检索它,它也不会返回导航属性。我仍然可以检索除我更新的实体之外的任何其他实体。 –