使用WCF数据服务时出错

时间:2011-06-29 14:19:48

标签: c# wcf linq linq-to-sql odata

我正在关注this指南,但我收到了错误消息。谁能帮我?

我的数据模型的代码在

之下
  namespace Datalayer {
    public class DataModel {

        public DataModel()
        {
            using (btWholesaleDataContext db = new btWholesaleDataContext()) {
                //! requires auth
                var MACRequestList = from r in db.btRequests
                                     select new Models.BT.Request {
                                         ID = r.ID,
                                         Date = r.DateTime,
                                         StatusCode = 3,
                                         Status = r.Status
                                     };

                MACRequests = MACRequestList.AsQueryable();

            }
        }

        public IQueryable<Models.BT.Request> MACRequests { get; private set; }
    }
}

Web服务提供错误

  

无法访问已处置的   object.Object name:'DataContext   Dispose后访问。'

当我访问MACRequests

我只发布了我认为已损坏的代码。如果你想看到更多,请告诉我。

4 个答案:

答案 0 :(得分:4)

您的数据上下文将放置在构造函数的末尾,位于using { }块的末尾。但是,当您使用IQueryable MACRequests属性时,它需要该基础上下文,该上下文已被处理。

处理此问题的一种可能方法是使您的类IDisposable并以这种方式处置上下文:

public class DataModel : IDisposable {

    private btWholesaleDataContext wholesaleDataContext;

    public DataModel()
    {
        wholesaleDataContext = new btWholesaleDataContext();
        //! requires auth
        var MACRequestList = ... ;

        MACRequests = MACRequestList.AsQueryable();
    }

    public IQueryable<Models.BT.Request> MACRequests { get; private set; }

    public void Dispose() {
        if(wholesaleDataContext != null)
            wholesaleDataContext.Dispose();
    }
}

然后你必须确保DataModel被任何使用它都妥善处理。

另一种方法是使MACRequests成为实际的项目列表而不是IQueryable:

public class DataModel {

    public DataModel()
    {
        using (btWholesaleDataContext db = new btWholesaleDataContext()) {
            //! requires auth
            var MACRequestList = ... ;

            MACRequests = MACRequestList.ToList(); // ToList reads the records now, instead of later.

        }
    }

    public List<Models.BT.Request> MACRequests { get; private set; }
}

答案 1 :(得分:2)

我认为是因为您使用的是IQueryable&lt;&gt;。它懒洋洋地查询服务。 使用列表&lt;&gt;相反,以便立即查询

或者将“btWholesaleDataContext db”变成成员变量

答案 2 :(得分:1)

对MACRequests的查询被推迟 - 一旦你离开使用块并且你的DataContext被处理掉,你将无法进行你想要的查询。

答案 3 :(得分:0)

您正在DataModel的构造函数中的using块中创建数据上下文...因此,当您访问MACRequests时,数据上下文已被释放。

请考虑以下事项:

public class DataModel : IDisposable {
    btWholesaleDataContext db = new btWholesaleDataContext();

    public void Dispose() 
    {
        btWholesaleDataContext.Dipose();
    }

    public IQueryable<Models.BT.Request> MACRequests { 
          get {
                                 return from r in db.btRequests
                                 select new Models.BT.Request {
                                     ID = r.ID,
                                     Date = r.DateTime,
                                     StatusCode = 3,
                                     Status = r.Status
                                 };
          } 
    }
}

请注意,此用法可用:

using (var dm = new DataModel())
{
   dm.MACRequests.ToArray();
}

但是这会因原来的原因而失败:

IQueryable<Models.BT.Request> requests = null;

using (var dm = new DataModel())
{
   requests = dm.MACRequests;
}   

// this will fail because the context is disposed by the time we force enumeration of the query
requests.ToArray();

...或者,由于WCF数据服务无法对投影进行过滤,因此您只能对查询进行所有操作

                                     from r in db.btRequests
                                     select new Models.BT.Request {
                                         ID = r.ID,
                                         Date = r.DateTime,
                                         StatusCode = 3,
                                         Status = r.Status
                                     };

执行它......

只考虑更改原始代码以返回数组或列表,而不是将其保留为可查询。