【问题标题】:EF Core - System.InvalidOperationException: ExecuteReader requires an open and available Connection. The connection's current state is closedEF Core - System.InvalidOperationException:ExecuteReader 需要打开且可用的连接。连接的当前状态为关闭
【发布时间】:2016-12-06 11:33:49
【问题描述】:

我正在使用 Entity Framework Core 运行 ASP.NET Core 1.0 Web 应用程序。当应用程序运行了一段时间(24 - 48 小时)后,应用程序开始在对任何端点或静态资源的每次请求时崩溃并抛出错误 System.InvalidOperationException: ExecuteReader requires an open and available Connection. The connection's current state is closed. 我只能通过重新启动应用程序池来恢复。

我正在像这样配置实体框架:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));   
}

我正在使用类似这样的扩展方法在 owin 管道中加载数据:

Startup.cs

app.LoadTenantData();

AppBuilderExtensions.cs:

public static void LoadTenantData(this IApplicationBuilder app)
    {
        app.Use(async (context, next) =>
        {
            var dbContext = app.ApplicationServices.GetService<ApplicationDbContext>();        
            var club = dbContext.Clubs.Single(c => c.Id == GetClubIdFromUrl(context));
            context.Items[PipelineConstants.ClubKey] = club;
            await next();
        });
    }

由于该错误仅在应用程序运行很长时间时才会出现,因此很难重现,但我假设它与EF打开和关闭连接不正确有关。

我该如何调试呢?我是否错误地使用了 EF?

【问题讨论】:

  • 你能在这里更新一下你是如何解决这个问题的!我遇到了同样的问题。我在有任何数据库查询的任何地方都使用异步和等待,当我进行负载测试时,这种情况持续出现在大约 30% 的情况下谢谢。
  • 我从未设法解决问题 - 最终使用操作过滤器将我的所有租户数据加载到 MVC 管道内:github.com/severisv/MyTeam/blob/master/src/MyTeam/Filters/… 只有在正确添加过滤器时才有效订购
  • @severin 你能再把它添加到github吗?找不到页面。

标签: c# entity-framework asp.net-core entity-framework-core


【解决方案1】:

我遇到了同样的问题。

我认为同一个 dbcontext 实例很可能正被多个线程同时使用。

你可能需要这个: services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")),ServiceLifetime.Transient); 有一个问题。 https://github.com/aspnet/EntityFramework/issues/6491

【讨论】:

  • 虽然我起初不相信现在我可以支持这一点,但在介绍了 lock 围绕一个执行多表插入错误的部分之后消失了。谢谢,秦。
  • 这帮助我意识到我的 Page 方法没有声明为异步,而我的服务方法(包含 EF 查询)是异步的。我正在更新到新编码的(异步)服务方法,而以前的版本不是异步的。谢谢!
【解决方案2】:

我的应用程序非常基础(快速编写,运行一次,然后忘记),因此解决上述问题的方法是在执行多表插入的部分周围简单地引入lock

    public void CallGooglePlacesAPIAndSetCallback(string websiteName)
    {
        using (var db = new WebAnalyzerEntities())
        {
            IList<IRecord> addressesToBeSearched = db.Rent.Where<IRecord>(o => o.Url.Contains(websiteName) && o.SpatialAnalysis.Count == 0).ToList().Union(db.Sale.Where<IRecord>(oo => oo.Url.Contains(websiteName) && oo.SpatialAnalysis.Count == 0)).ToList();
            foreach (var locationTobeSearched in addressesToBeSearched)
            {
                try
                {
           //this is where I introduced the lock
                    lock (_lock)
                    {
                        dynamic res = null;
                        using (var client = new HttpClient())
                        {
                            while (res == null || HasProperty(res, "next_page_token"))
                            {
                                var url = $"https://maps.googleapis.com/maps/api/geocode/json?address={locationTobeSearched.Address}&key={googlePlacesApiKey}&bounds=51.222,-11.0133788|55.636,-5.6582363";
                                if (res != null && HasProperty(res, "next_page_token"))
                                    url += "&pagetoken=" + res["next_page_token"];
                                var response = client.GetStringAsync(url).Result;
                                JavaScriptSerializer json = new JavaScriptSerializer();
                                res = json.Deserialize<dynamic>(response);
                                if (res["status"] == "OK")
                                {
                                    Tuple<decimal?, decimal?, string> coordinatesAndPostCode = ReadResponse(res["results"][0]);
                                    if (coordinatesAndPostCode != null && coordinatesAndPostCode.Item1.HasValue && coordinatesAndPostCode.Item2.HasValue)
                                    {
           //this is the line where exception was thrown
                                        locationTobeSearched.SpatialAnalysis.Add(new SpatialAnalysis() { Point = CreatePoint(coordinatesAndPostCode.Item1.Value, coordinatesAndPostCode.Item2.Value) });
                                        locationTobeSearched.PostCode = coordinatesAndPostCode.Item3;
                                    }
                                }
                                else if (res["status"] == "OVER_QUERY_LIMIT")
                                {
                                    return;
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {

                }

                db.SaveChanges();
            }
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-02
    相关资源
    最近更新 更多