好吧,我想,准备阅读一篇很长的帖子,因为它非常复杂。
我正在使用Entity Framework与Microsoft Unity以及存储库和工作单元的自定义实现。
首先,我确实有一个存储库:
public class Repository<TEntity> : RepositoryBase<TEntity>,
IRepository<TEntity>
where TEntity : class
{
#region Constructors
public Repository(IDbContext context, UnitOfWork unitOfWork)
: base(context, unitOfWork)
{ }
#endregion
#region Properties
private bool _disposed;
#endregion
#region Methods
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
Context.Dispose(); // Dispose the main context.
}
}
_disposed = true;
}
#endregion
// Extra code has been removed for clarity.
}
我想这很简单,我有一个存储库,存储库依赖于IDbContext(自定义接口),并且实现了我在这里实现的基础clsses中定义的IDisposable接口。
当我处理对象时,我在上下文中调用Dispose(),这应该足够了。
接下来,我有UnitOfWork:
/// <summary>
/// Provides methods that respond to actions executed in a <see cref="IUnitOfWork"/>.
/// </summary>
public class UnitOfWork : IUnitOfWork
{
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="IUnitOfWork"/> with a given <see cref="IDbContext"/>.
/// </summary>
/// <param name="context">The <see cref="IDbContext"/> in which the entities are available.</param>
public UnitOfWork(IDbContext context)
{
_context = context;
}
#endregion
#region Properties
/// <summary>
/// The <see cref="IDbContext"/> in which the entities are available.
/// </summary>
protected readonly IDbContext _context;
/// <summary>
/// Provides a way to identify if the <see cref="UnitOfWork"/> has been disposed.
/// </summary>
private bool _disposed;
#endregion
#region IUnitOfWork Members
// Extra code removed for clarity.
public virtual void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_context.Dispose(); // Dispose the main context.
}
}
_disposed = true;
}
#endregion
}
作为存储库,此类也采用IDbContext,并包含IDispose接口,在dispose方法中我处理上下文。
然后我有另一个UnitOfWork,它继承自上面的那个。我在这个工作单元中定义了我的存储库:
public class UnitOfWork : Repository.UnitOfWork
{
#region Constructors
public UnitOfWork(IDbContext context)
: base(context)
{
_pageRepository = new Repository<Page>(context, this);
}
#endregion
#region Properties
private readonly IRepository<Page> _pageRepository;
public IRepository<Page> PageRepository { get { return _pageRepository; } }
private bool _disposed;
#endregion
#region Methods
public override void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
base.Dispose();
}
protected override void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// Disposes all the repositories.
PageRepository.Dispose();
// Disposes the main context.
_context.Dispose();
}
}
_disposed = true;
}
#endregion
}
所以,在这里我从其他UnitOfWork中覆盖Dispose方法,它处理上下文并且我在这里处理PageRepository,之后,我调用应该处理上下文的base.Dispose()
方法。
我的IDbContext实现是一个DbContext(实体框架实现):
public class OxygenDataContext : DbContext, IDbContext
{
#region Constructors
public OxygenDataContext() :
base("Ox")
{ }
#endregion
#region Properties
public IDbSet<Page> Page { get; set; }
#endregion
#region IDbContext Members
public IRepositoryEntityCollection<TEntity> Set<TEntity>() where TEntity : class
{ return new RepositoryEntityCollection<TEntity>(this); }
public new void SaveChanges()
{ base.SaveChanges(); }
#endregion
}
因此,默认情况下,这已经实现了IDisposable接口。
现在,我有Unity将接口解析为具体类型:
container.RegisterType<IDbContext, OxygenDataContext>(new PerRequestLifetimeManager());
container.RegisterType<IUnitOfWork, UnitOfWork>(new PerRequestLifetimeManager());
在global.asax文件中,我将对象放在EndRequest中(我显然需要这段代码,因为否则似乎没有调用dispose):
protected void Application_EndRequest(object sender, EventArgs e)
{
var container = DependencyResolver.Current.GetService<IUnityContainer>();
container.Resolve<IDbContext>().Dispose();
container.Resolve<IUnitOfWork>().Dispose();
}
但是,当我现在打开一个页面并从正在工作的数据库中检索内容时,当我直接使用SQL Server Management Explorer更改数据库中的数据并刷新页面时,页面仍会显示然而,旧的数据我认为一切都正确处理。
任何人都有这个想法,这让我疯了吗?
修改
似乎正在处理上下文,但我正在使用VirtualFileProvider并且它们的返回值未更新。
此外,当应用程序启动并且我按下CTRL-F5(保持按下)时,将弹出各种错误,其中一个是:
ExecuteReader需要一个开放且可用的连接。连接的当前状态是打开的。
这是实体框架中的预期行为吗?
答案 0 :(得分:1)
好的,我发现了这个问题。
我遇到的问题是在MVC的VirtualFileProvider中,我在那里使用了存储库而没有处理它们。
我已对其进行了修改,因此现在使用Using
语句检索数据以连接到数据库。
所有问题都已经消失了。