有没有办法重置DbContext而不处理和重新实例化?

dev*_*xer 9 entity-framework entity-framework-4 entity-framework-4.1

我最近重构了一个WPF应用程序,以便它不再包含DbContext在using子句中的每次使用(请参阅此问题).相反,我的应用程序只使用相同的DbContext单例.

除了一个小问题外,这很有用.我有一个例程,从头开始重建数据库并插入一些默认数据.此例程直接使用ADO.NET(而不是DbContext),因此DbContext不知道数据库现在完全不同.

有没有一种方法来重置DbContext而不处理它?如果可能的话,我想避免处置,因为这会破坏整个应用程序中对原始单例的几个引用.

dev*_*xer 7

我无法想出一种重置全局DbContext的方法.然而,我能够通过向DbContextLocator需要DbContext的任何类中注入一个而不是传递DbContext本身来解决我的问题.

我的目标是维护一个全局DbContext,但允许它在需要时重置(例如在数据库重建或导入之后).

我的解决方案使用抽象基类和具体类.

基类

using System.Data.Entity;

namespace CommonLibrary.Database
{
    public abstract class DbContextLocator
    {
        private DbContext _dbContext;

        public DbContext Current
        {
            get { return _dbContext; }
        }

        public DbContextLocator()
        {
            _dbContext = GetNew();
        }

        public virtual void Reset()
        {
            _dbContext.Dispose();
            _dbContext = GetNew();
        }

        protected abstract DbContext GetNew();
    }
}
Run Code Online (Sandbox Code Playgroud)

混凝土类

using System.Data.Entity;
using CommonLibrary.Database;
using ExperimentBase.EntityModels;

namespace MainProject.Models    
{
    public class MainDbContextLocator : DbContextLocator
    {
        public new MainDbContext Current
        {
            get { return (MainDbContext)base.Current; }
        }

        protected override DbContext GetNew()
        {
            return new MainDbContext();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

用法

获取当前的DbContext:

var dbContext = dbContextLocator.Current;
Run Code Online (Sandbox Code Playgroud)

重置DbContext:

dbContextLocator.Reset();
//Note: normally followed by code that re-initializes app data
Run Code Online (Sandbox Code Playgroud)

编辑

根据Shimmy的反馈,我制作DbContextLocatorBase了一个通用的.(我现在也正在实施IDisposable.)

基类

public class DbContextLocator<TContext> : IDisposable
    where TContext : DbContext, new()
{
    private TContext _dbContext;

    public TContext Current
    {
        get { return _dbContext; }
    }

    public DbContextLocator()
    {
        _dbContext = GetNew();
    }

    public virtual void Reset()
    {
        _dbContext.Dispose();
        _dbContext = GetNew();
    }

    protected virtual TContext GetNew()
    {
        return new TContext();
    }

    public void Dispose()
    {
        _dbContext.Dispose();
    }
}
Run Code Online (Sandbox Code Playgroud)

具体类(可选,因为基类不再是抽象的)

public class MainDbContextLocator : DbContextLocator<MainDbContext> { }
Run Code Online (Sandbox Code Playgroud)


Ian*_*cer 5

在应用程序的生命周期内保持ObjectContext打开通常是个坏主意.

ObjectContext(在本例中为DbContext)用于工作单元.

请参阅实体框架和连接池