处理datacontext会导致读取器关闭时无效尝试调用Read

时间:2009-12-24 20:08:40

标签: .net asp.net-mvc linq-to-sql using using-statement

我正在构建一个MVC 2应用程序,并将linq用于存储过程的sql。

我创建了一个数据访问层,它有一个内部datacontext类和一个公开应用程序的公共类。在我的公共类中,我公开了访问datacontext类的方法,并使用linq将数据转换为我自己的对象模型类。

在我的公共课中,我将使用以下模式公开一个方法:

public IEnumerable<MyObject> ListObjects(int iParameter)
{
    using (MyDataContext db = new MyDataContext)
    {
        //call stored proc and convert results to my object model
        return db.List_Objects().Select(o => new MyObject()
            {
                ID = o.ID,
                Name = o.Name
                Text = o.Code + " " + o.Description
            };
    } 
} 

我的MVC应用程序将从模型类调用此方法,并且aspx将遍历结果。我发现我总是得到一个错误“datacontext导致无效尝试在读取器关闭时调用Read”因为我将数据上下文使用包装在一个使用范围内。如果我不使用using子句中的所有内容,它可以正常工作。这是为什么?

我认为这不一定是linq或mvc的东西(但不确定),是否导致在返回所有对象之前调用dispose的using子句?或者也许select子句只是在枚举器通过类似于yield的工作方式进行迭代时执行?

2 个答案:

答案 0 :(得分:3)

Linq to Sql使用工作单元模式来封装对配置的数据库的访问(使用范围的结束)关闭与数据库的连接,当你不包装语句时它工作的原因是上下文仍然存在当冒充查询时(由于它可能会导致连接保持打开状态可能会很糟糕),它会抛出,因为执行只会在您第一次使用IEnumerable时发生,而IEnumerable可能位于某个地方,直到视图为止,您需要做的是使用ToList()将{{1}}转换为列表,这将立即强制执行,而不是延迟执行,以便连接关闭,您将拥有自己的收藏。

答案 1 :(得分:1)

使用会持续调用方法,所以如果你有这个:

var objects = ListObjects(123);

然后创建并处理了DataContext,但尚未返回任何结果。

当你开始枚举结果时:

foreach(var o in objects)

方法表达式树开始执行查询,但是已经处理了datacontext,因此无法打开新连接。

这样的东西可行,但它阻止了从外部ListObjects“扩展”查询的能力。

public IEnumerable<MyObject> ListObjects(int iParameter)
{
    List<MyObject> objects;
    using (MyDataContext db = new MyDataContext())
    {
        //call stored proc and convert results to my object model
        objects = (db.List_Objects().Select(o => new MyObject()
            {
                ID = o.ID,
                Name = o.Name
                Text = o.Code + " " + o.Description
            }).ToList();
    } 
    return objects;
}

如果您了解何时处理上下文,并且何时可以不这样做,那么IMO是安全的。