为什么我的DbContext没有被处理掉,或者为什么它没有按预期工作

时间:2014-10-09 08:04:28

标签: c# .net asp.net-mvc entity-framework unity-container

好吧,我想,准备阅读一篇很长的帖子,因为它非常复杂。

我正在使用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需要一个开放且可用的连接。连接的当前状态是打开的。

这是实体框架中的预期行为吗?

1 个答案:

答案 0 :(得分:1)

好的,我发现了这个问题。

我遇到的问题是在MVC的VirtualFileProvider中,我在那里使用了存储库而没有处理它们。

我已对其进行了修改,因此现在使用Using语句检索数据以连接到数据库。 所有问题都已经消失了。