[英]Using singleton pattern with Entity Framework context - The underlying provider failed on open
I'm trying to add a singleton pattern to my DbContext with Entity Framework. 我正在尝试使用Entity Framework将单例模式添加到我的DbContext中。 I've always used the singleton pattern for this, and never experienced this error before. 我一直为此使用单例模式,以前从未遇到过此错误。 I know that singleton is best practice (Apparently not) , but if any of you have the time to spare, could you please explain why singleton is best practice? 我知道单例是最佳实践 (显然不是) , 但是如果你们中有空余的时间,您能解释一下为什么单例是最佳实践吗?
Problem 问题
Other than that, I get this error: 除此之外,我得到这个错误:
The underlying provider failed on open 基础提供程序在打开时失败
Let's have a look at my code 让我们看看我的代码
DAO.cs DAO文件
public class DAO
{
private static HourRegistrationEntities hourRegInstance;
public static HourRegistrationEntities HourRegInstance { get { return hourRegInstance = hourRegInstance ?? new HourRegistrationEntities(); } }
}
Service.cs (example method) Service.cs(示例方法)
/// <summary>
/// Return a list of all denied Hour Registration for the Login with the given stringId
/// </summary>
/// <param name="stringId"></param>
/// <returns>A list of HourRegistrationDTO</returns>
public List<HourRegistrationDTO> GetAllDeniedHoursForLogin(string stringId)
{
var id = Int32.Parse(stringId);
using (var db = DAO.HourRegInstance)
{
var dbHours = db.HourRegistration.Where(x => x.LoginProject.Login.ID == id && x.Denied == true).ToList();
var returnList = new List<HourRegistrationDTO>();
foreach (var item in dbHours)
{
returnList.Add(new HourRegistrationDTO()
{
Id = item.ID,
Hours = item.Hours,
Date = item.Date.ToShortDateString(),
Comment = item.Comment,
CommentDeny = item.CommentDeny,
LoginProject = new LoginProjectDTO()
{
Project = new ProjectDTO()
{
Title = item.LoginProject.Project.Title
}
}
});
}
return returnList;
}
}
As mentioned, I've ALWAYS used the singleton pattern but NEVER had this error before. 如前所述,我一直使用Singleton模式,但从来没有过这样的错误。 What's causing this, and why? 是什么原因造成的,为什么?
UPDATE: 更新:
I basically do like this (code below) instead, as that solves the problem. 我基本上是这样做的(下面的代码),因为这样可以解决问题。 Now I'm more curious about what's causing the error. 现在,我对引起错误的原因更加好奇。
Service.cs Service.cs
using (var db = new HourRegistrationEntities())
The reason it doesn't work is that your using
clause is disposing your singleton instance after first use. 它不起作用的原因是您的using
子句是在第一次使用后处置您的单例实例。 After that, it becomes useless, disposed but still not null. 在那之后,它变得无用,被丢弃,但仍然不是null。
The fact that you insist you always used singletons and it always worked doesn't really mean anything. 您坚持使用单例并且总是有效的事实并没有任何意义。 Using singletons for data contexts is considered a terribly bad habit that leads to numerous issues, including memory, concurrency and transaction problems. 将单例用于数据上下文被认为是一种非常糟糕的习惯,它导致许多问题,包括内存,并发性和事务问题。
My guess is that before you always worked on single threaded desktop apps where a singleton is still risky but doesn't lead to immediate issues. 我的猜测是,在您始终使用单线程桌面应用程序之前,单例仍然有风险,但不会导致直接问题。 Here, however, in a concurrent world of a web service, it just won't work. 但是,在这里,在Web服务的并发世界中,它只是行不通的。
On the other hand, creating a new instance per a wcf call is perfectly valid, different instances do not interfere and you correctly dispose them after used. 另一方面,每个wcf调用创建一个新实例是完全有效的,不同的实例不会相互干扰,您可以在使用后正确处置它们。
Make sure you have this code as your constructor: 确保您具有以下代码作为构造函数:
public HourRegistrationEntities()
: base("ConnectionStringName")
{
}
And then define a connection string in App.config
/ web.config
named ConnectionStringName
然后在App.config
/ web.config
定义一个名为ConnectionStringName
的连接字符串
This will most probably solve your problem. 这很可能会解决您的问题。 Now about the singleton: you're creating a new instance of HourRegistrationEntities
on each call to GetAllDeniedHoursForLogin
which is not singleton pattern, it's Unit of Work pattern which is THE best practice for EntityFramework. 现在关于单身:你要创建的新实例HourRegistrationEntities
每次调用GetAllDeniedHoursForLogin
这不是单例模式,它的单位工作模式是对的EntityFramework的最佳实践。 Keep using it and forget about singleton DbContext, unless you REALLY know what you do. 继续使用它,而不必担心单例DbContext,除非您真的知道自己要做什么。 As EF keeps track of entities and their relationship, a long lived singleton DbContext will get slow over time. 随着EF跟踪实体及其关系,长期存在的单例DbContext将随着时间的流逝而变慢。 There will be many other strange problems, like unsaved transactions, side effects and many other hard to debug problems. 还有许多其他奇怪的问题,例如未保存的事务,副作用以及许多其他难以调试的问题。
May I suggest you to use "lock" functionality to access your singleton object : 我可以建议您使用“锁定”功能来访问您的单例对象:
public sealed class XModelInstance
{
private static XDBEntities edmx = null;
private static readonly object padlock = new object();
private XModelInstance() { }
public static XDBEntities Edmx
{
get
{
lock (padlock)
{
if (edmx == null)
{
edmx = new XDBEntities();
}
return edmx;
}
}
}
}
This will avoid concurrent access to your context. 这样可以避免同时访问您的上下文。 And of course do not use "using" clause any more to access your context :) 当然,不要再使用“ using”子句来访问您的上下文了:)
Call example: 通话示例:
var dbHours = XModelInstance.Edmx.HourRegistration.Where(...);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.