使用语句后如何访问相关对象已在Entity Framework中完成?

时间:2012-11-05 16:30:24

标签: c# entity-framework

我在VS 2010中使用EF 3.5。我有一个返回结构的方法。在结构中有一个对象armatuur。返回结构时,我想从armatuur实例访问相关对象。

然而

返回struct的方法:

public LampPostDetail getLamppostInfo(int id)
{
    LampPostDetail lpd;

    lpd.xPos = 0;
    lpd.ypos = 0;
    lpd.armatuur = new Armatuur();

    //get the info from object
    using (var db = new OvisionDBEntities())
    {
        var objects = from o in db.Objects
                      where o.ObjectId == id
                      select o;

        foreach (OVSL.Data.Object o in objects)
        {
            lpd.xPos = o.XCoordinatie;
            lpd.ypos = o.YCoordinatie;
            lpd.armatuur = o.Armatuur; //which is a table in my db
        }

        return lpd;
    }
}

结构:

public struct LampPostDetail
{
    #region [ Data Members (14)]
    //lamppost info
    public double? xPos;
    public double? ypos;

    //a lamppost can have several armaturen
    public OVSL.Data.Armatuur armatuur; //is a table in my db

    #endregion [ Data Members ]
}

在我的客户端执行此操作时:

 LampPostDetail lpd = client.getLamppostInfo(id);
 string brand = lpd.armatuur.producer.name; //producer is related object of armatuur

我得到一个ObjectDisposedException。我知道这是因为LampPostDetail对象在使用块完成后被释放。但我如何让这个工作?在我将其返回给客户之前,检索我需要的所有信息(例如品牌名称)不是一种选择。

2 个答案:

答案 0 :(得分:0)

它不是你正在处理的LampPostDetail,它是你从它引用的数据库中检索到的Armatuur对象,或者是Armatuur引用的对象。

我可以看到两种方法来解决这个问题。第一种方法是将Entity上下文作为getLamppostInfo info方法的可选参数。由于您使用的是3.5,因此必须执行重载以保持原始功能:

public LampPostDetail getLamppostInfo(int id,OvisionDBEntities context)
{
...
    try
    {
       OvisionDBEntities db;
       if (context == null)
          db = new OvisionDBEntities();
       else
          db = context;
    ...
    }
    finally
    {
       if (context == null && db != null)
         db.Dispose() // or close maybe
    }

    retun lpd;

 }

 // Overloaded function to keep orignal functionality (C# 3.5 does not have 
 // optional parameters)
 public LampPostDetail getLamppostInfo(int id)
 {
     return LampPostDetail(id,null)
 }

现在您可以将其命名为:

using (var db = new OvisionDBEntities())
{
   LampPostDetail lpd = client.getLamppostInfo(id,db);
   string brand = lpd.armatuur.producer.name;
}    

当您尝试引用它们时,您的对象仍然存在。

另一种选择是在处理之前将引用的对象与实体上下文分离。

  db.Detach(o.Armatuur); 

但是,我不相信分离该对象的任何对象引用。所以你必须对参考树进行交互并分离对象。

答案 1 :(得分:0)

这里唯一要处理的是OvisionDBEntities上下文。之后,不可能进行延迟加载。怎么处理?实际上,您的问题是:您可以做些什么来随时向用户提供用户操作可能需要的所有数据?我看到三个或四个选项:

  1. 在上下文处理后启用对实体导航属性的访问的标准方法是调用Includefrom o in db.Objects.Include("Armatuur.Producer")...但这显然不适合您。

  2. 让上下文生效并依赖延迟加载来按需获取数据。这可能是您的选择。但是,随着内部变更跟踪记录的增长,长期存在的上下文可能会导致性能逐渐下降等问题,并且过时的缓存数据会导致刷新/重新加载语句遍布整个地方。

  3. 代替导航属性/延迟加载从服务/存储库层按需获取数据,该服务/存储库层使用每个调用的上下文实例。我认为这个选项适合你。

  4. 更多功能而不是技术选项:设计可以使用较少数据的用例(这样Include可能就足够了)。没有人可以接纳数千行和数十列的网格。精心设计的用户交互可以大大减少泵入客户端的数据量(仅在开始时才开始)。