0

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

然而

返回结构的方法:

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 对象在 using 块完成后被释放。但是我怎样才能让它工作呢?在我将其返回给客户之前检索我需要的所有信息(例如品牌名称)不是一种选择。

4

2 回答 2

0

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

我可以看到解决此问题的两种选择。第一个是使实体上下文成为您的 getLamppostInfo 信息方法的可选参数。由于您使用的是 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); 

但是,我不相信会分离该对象引用的任何对象。因此,您还必须对参考树进行交互并分离对象。

于 2012-11-05T17:56:45.927 回答
0

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

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

  2. 让上下文存在并依赖延迟加载来按需获取数据。这可能是您的一个选择。但是长期存在的上下文可能会导致问题,例如随着内部更改跟踪记录的增长而逐渐降低性能,以及导致刷新/重新加载语句分散在各处的过时缓存数据。

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

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

于 2012-11-05T23:56:42.927 回答