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

时间:2011-04-13 01:54:51

标签: entity-framework entity-framework-4 entity-framework-4.1

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

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

是否有方法重置DbContext而不进行处理?如果可能的话,我想避免处置,因为这会破坏整个应用程序中对原始单例的几个引用。

3 个答案:

答案 0 :(得分:6)

我无法想出一种重置全局DbContext的方法。但是,我能够通过向需要DbContext的任何类中注入DbContextLocator而不是传递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();
    }
}

具体类

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();
        }
    }
}

<强>用法

获取当前的DbContext:

var dbContext = dbContextLocator.Current;

重置DbContext:

dbContextLocator.Reset();
//Note: normally followed by code that re-initializes app data

修改

根据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();
    }
}

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

public class MainDbContextLocator : DbContextLocator<MainDbContext> { }

答案 1 :(得分:5)

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

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

请参阅Entity Framework and Connection Pooling

答案 2 :(得分:1)

Entity Framework Core 5.0 现在具有执行此操作的 ChangeTracker.Clear() 方法。如 the documentation 中所述,最好根据需要创建和处置 DbContext 实例,但有时这不切实际。

<块引用>

DbContext 旨在具有较短的生命周期,其中新实例 是为每个工作单元创建的。这种方式意味着所有跟踪 当上下文在每个结束时被丢弃时实体被丢弃 工作单元。但是,使用此方法清除所有跟踪的实体 在创建新上下文实例的情况下可能很有用 不实用。