我正在使用实体框架,偶尔我会得到这个错误。

EntityCommandExecutionException
{"There is already an open DataReader associated with this Command which must be closed first."}
   at System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands...

即使我没有做任何手动连接管理。

此错误间歇性地发生。

触发错误的代码(为方便阅读而缩短):

        if (critera.FromDate > x) {
            t= _tEntitites.T.Where(predicate).ToList();
        }
        else {
            t= new List<T>(_tEntitites.TA.Where(historicPredicate).ToList());
        }

使用Dispose模式以便每次都打开新的连接。

using (_tEntitites = new TEntities(GetEntityConnection())) {

    if (critera.FromDate > x) {
        t= _tEntitites.T.Where(predicate).ToList();
    }
    else {
        t= new List<T>(_tEntitites.TA.Where(historicPredicate).ToList());
    }

}

仍然有问题

为什么EF不重用一个连接,如果它已经打开。


当前回答

我注意到,当我发送一个iquerible到视图并在双foreach中使用它时,这个错误发生了,其中内部foreach也需要使用连接。简单的例子(ViewBag。parent可以是iqueryable或者DbSet):

foreach (var parent in ViewBag.parents)
{
    foreach (var child in parent.childs)
    {

    }
}

简单的解决方案是在使用集合之前对其使用. tolist()。还要注意,MARS不能与MySQL一起工作。

其他回答

在我的情况下,问题发生是因为依赖注入注册。我正在将每个请求范围的服务注入到一个单例注册服务中,该服务使用dbcontext。因此在多个请求中使用了dbcontext,因此出现了错误。

我注意到,当我发送一个iquerible到视图并在双foreach中使用它时,这个错误发生了,其中内部foreach也需要使用连接。简单的例子(ViewBag。parent可以是iqueryable或者DbSet):

foreach (var parent in ViewBag.parents)
{
    foreach (var child in parent.childs)
    {

    }
}

简单的解决方案是在使用集合之前对其使用. tolist()。还要注意,MARS不能与MySQL一起工作。

通过向构造函数中添加选项,我轻松地(实用地)解决了这个问题。因此,我只在需要时使用它。

public class Something : DbContext
{
    public Something(bool MultipleActiveResultSets = false)
    {
        this.Database
            .Connection
            .ConnectionString = Shared.ConnectionString /* your connection string */
                              + (MultipleActiveResultSets ? ";MultipleActiveResultSets=true;" : "");
    }
...

我最初决定在我的API类中使用一个静态字段来引用MyDataContext对象的实例(其中MyDataContext是一个EF5 Context对象),但这似乎是造成问题的原因。我在每个API方法中都添加了如下代码,从而解决了这个问题。

using(MyDBContext db = new MyDBContext())
{
    //Do some linq queries
}

正如其他人所说,EF数据上下文对象不是线程安全的。因此,在适当的条件下,将它们放置在静态对象中最终会导致“数据读取器”错误。

我最初的假设是只创建对象的一个实例会更有效,并提供更好的内存管理。从我研究这个问题所收集到的资料来看,情况并非如此。事实上,将对API的每个调用视为一个独立的线程安全事件似乎更有效。确保当对象超出作用域时,所有资源都被适当释放。

这是有意义的,特别是如果你把你的API带到下一个自然的进程,即将它公开为WebService或REST API。

信息披露

操作系统:Windows Server 2012 .NET:安装4.5,项目使用4.0 数据来源:MySQL 应用程序框架:MVC3 身份验证:形式

如果我们试图将部分条件分组到Func<>或扩展方法中,我们将得到这个错误,假设我们有这样的代码:

public static Func<PriceList, bool> IsCurrent()
{
  return p => (p.ValidFrom == null || p.ValidFrom <= DateTime.Now) &&
              (p.ValidTo == null || p.ValidTo >= DateTime.Now);
}

Or

public static IEnumerable<PriceList> IsCurrent(this IEnumerable<PriceList> prices) { .... }

这将抛出异常,如果我们试图在Where()中使用它,我们应该做的是构建一个这样的Predicate:

public static Expression<Func<PriceList, bool>> IsCurrent()
{
    return p => (p.ValidFrom == null || p.ValidFrom <= DateTime.Now) &&
                (p.ValidTo == null || p.ValidTo >= DateTime.Now);
}

更多信息请访问:http://www.albahari.com/nutshell/predicatebuilder.aspx