简体   繁体   English

在实体框架上下文中使用单例模式-基础提供程序在打开时失败

[英]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.

相关问题 基础提供程序无法打开-WPF和实体框架 - The underlying provider failed to open - WPF and Entity FrameWork 实体框架底层提供程序在打开时失败 - Entity Framework The underlying provider failed on Open 实体框架异常“底层提供程序打开失败” - Entity Framework Exception “The underlying provider failed on Open” 基础提供程序在实体框架中打开时失败 - The underlying provider failed on Open in entity framework connection SQLite&Entity Framework 6“基础数据提供程序无法打开” - SQLite & Entity Framework 6 “The underlying data provider failed to open” 实体框架:基础提供程序在打开时失败-通过WCF服务 - Entity Framework: The underlying provider failed on Open - through WCF service 实体框架给出异常:“底层提供程序在打开时失败。” - Entity Framework giving exception : “The underlying provider failed on Open.” WCF和实体框架和SQL Server - “底层提供程序在Open上失败” - WCF & Entity Framework & SQL Server - “The underlying provider failed on Open” 带有 Unity 的实体框架“底层提供程序在 Open 上失败”。 - Entity framework with Unity “The underlying provider failed on Open.” NServiceBus和实体框架导致异常-基础提供程序在打开时失败 - NServiceBus and Entity Framework causes exception - The underlying provider failed on Open
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM