EF MVC连接';s的当前状态为打开,或者在发送多个请求时下划线提供程序无法打开
本文关键字:请求 程序 下划线 连接 MVC EF 状态 或者 | 更新日期: 2023-09-27 18:24:05
我们有一个MVC 4中的web应用程序,使用Entity Framework 6.1,并使用unity作为DI框架。当我们向一个页面发送许多请求时,我们得到了以下错误:"连接的当前状态是打开的"或有时"下划线提供程序无法打开"我认为这应该是由多线程使用UnitOfWork或DbContex的一个实例引起的,但我们检查了一下,没有发现任何错误,这是我们的代码
///////////////////////////////////////////////////////////////数据库工厂
public class DatabaseFactory : Disposable, IDatabaseFactory
{
private MyDbContext dataContext;
public MyDbContext Get()
{
var context= dataContext ?? (dataContext = new MyDbContext());
return context;
}
protected override void DisposeCore()
{
var dataContextAdapter = dataContext as IObjectContextAdapter;
if (dataContextAdapter != null && dataContextAdapter.ObjectContext.Connection.State == ConnectionState.Open)
dataContextAdapter.ObjectContext.Connection.Close();
if (dataContext != null)
dataContext.Dispose();
}
}
///////////////////////////////////////////////////////////////单位工作
public class UnitOfWork :Disposable, IUnitOfWork
{
private readonly IDatabaseFactory databaseFactory;
private MyDbContext dataContext;
private LogContext logContext;
public UnitOfWork(IDatabaseFactory databaseFactory)
{
this.databaseFactory = databaseFactory;
}
protected override void DisposeCore()
{
var dataContextAdapter = dataContext as IObjectContextAdapter;
if (dataContextAdapter != null && dataContextAdapter.ObjectContext.Connection.State==ConnectionState.Open)
dataContextAdapter.ObjectContext.Connection.Close();
if (dataContext != null)
dataContext.Dispose();
if (databaseFactory != null)
databaseFactory.Dispose();
}
protected MyDbContext DataContext
{
get { return (dataContext = databaseFactory.Get()); }
}
public bool Commit()
{
try
{
DataContext.SaveChanges();
return true;
}
catch (Exception)
{
return false;
}
}
}
///////////////////////////////////////////////////////////////存储库库
public abstract class RepositoryBase<T> : Disposable where T : class
{
private MyDbContext dataContext;
private readonly IDbSet<T> dbset;
protected RepositoryBase(IDatabaseFactory databaseFactory)
{
DatabaseFactory = databaseFactory;
dbset = DataContext.Set<T>();
}
protected override void DisposeCore()
{
var dataContextAdapter = dataContext as IObjectContextAdapter;
if (dataContextAdapter != null && dataContextAdapter.ObjectContext.Connection.State == ConnectionState.Open)
dataContextAdapter.ObjectContext.Connection.Close();
if (dataContext != null)
dataContext.Dispose();
}
protected IDatabaseFactory DatabaseFactory
{
get;
private set;
}
protected MyDbContext DataContext
{
get { return dataContext ?? (dataContext = DatabaseFactory.Get()); }
}
public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where)
{
return dbset.Where(where).ToList();
}
}
///////////////////////////////////////////////////////////////UnityRegister类型
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<IDatabaseFactory, DatabaseFactory>(new HttpContextLifetimeManager<IDatabaseFactory>())
.RegisterType<IUnitOfWork, UnitOfWork>(new HttpContextLifetimeManager<IUnitOfWork>())
.RegisterType<IMyDbContext, MyDbContext>(new HttpContextLifetimeManager<IMyDbContext>())
.RegisterType(typeof(IRepository<>), typeof(RepositoryBase<>))
//Orders
.RegisterType<IOrdersRepository, OrdersRespository>(new HttpContextLifetimeManager<IOrdersRepository>())
.RegisterType<IOrdersService, OrdersService>(new HttpContextLifetimeManager<IOrdersService>())
//Orders
....
}
任何建议和建议都将不胜感激
在我看来,正是这行代码给您带来了问题:
.RegisterType<IMyDbContext, MyDbContext>(new HttpContextLifetimeManager<IMyDbContext>())
我们的代码中也有类似的问题,因为DbContext不是线程安全的,但在不同的请求之间共享它通常不是一个好主意。相反,我们这样做了,并且没有任何连接问题:
.RegisterType<IMyDbContext, MyDbContext>(new PerRequestLifetimeManager())
这样,每个请求都会创建一个新的上下文实例。此外,DbContext实现IDisposable,因此如果您想手动控制DbContext的实例化和处理,那么您可以简单地执行:
using (var context = new MyDbContext())
{
}
我发现了问题,我们有一个CustomFilterAttribute,如下所示:
public class CustomFilters : ActionFilterAttribute
{
[Dependency]
public ICustomersService CustomersService { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
如果我删除这个过滤器并覆盖Controller中的OnActionExecuting,那么它将不会出现问题
我们正在使用此提供程序将类型注入过滤器
public class UnityFilterAttributeFilterProvider : FilterAttributeFilterProvider
{
private IUnityContainer _container;
public UnityFilterAttributeFilterProvider(IUnityContainer container)
{
_container = container;
}
protected override IEnumerable<FilterAttribute> GetControllerAttributes(
ControllerContext controllerContext,
ActionDescriptor actionDescriptor)
{
var attributes = base.GetControllerAttributes(controllerContext,
actionDescriptor);
foreach (var attribute in attributes)
{
_container.BuildUp(attribute.GetType(), attribute);
}
return attributes;
}
protected override IEnumerable<FilterAttribute> GetActionAttributes(
ControllerContext controllerContext,
ActionDescriptor actionDescriptor)
{
var attributes = base.GetActionAttributes(controllerContext,
actionDescriptor);
foreach (var attribute in attributes)
{
_container.BuildUp(attribute.GetType(), attribute);
}
return attributes;
}
}
我们使用以下
var oldProvider = FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider);
FilterProviders.Providers.Remove(oldProvider);
var container = new UnityContainer();
var provider = new UnityFilterAttributeFilterProvider(container);
FilterProviders.Providers.Add(provider);
UnityConfig.RegisterTypes(container);
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
我们还更改了使用"PerrequestLifeTimeManager"注册的所有类型,但没有任何更改,这有什么问题?