我最近重构了一个WPF应用程序,以便它不再在using
子句中包含对DbContext的每次使用(请参阅this question)。相反,我的应用程序只使用相同的DbContext单例。
除了一个小问题外,这很有用。我有一个例程,从头开始重建数据库并插入一些默认数据。此例程直接使用ADO.NET(而不是DbContext),因此DbContext不知道数据库现在完全不同。
是否有方法重置DbContext而不进行处理?如果可能的话,我想避免处置,因为这会破坏整个应用程序中对原始单例的几个引用。
答案 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)用于工作单元。
答案 2 :(得分:1)
Entity Framework Core 5.0 现在具有执行此操作的 ChangeTracker.Clear()
方法。如 the documentation 中所述,最好根据需要创建和处置 DbContext
实例,但有时这不切实际。
DbContext
旨在具有较短的生命周期,其中新实例
是为每个工作单元创建的。这种方式意味着所有跟踪
当上下文在每个结束时被丢弃时实体被丢弃
工作单元。但是,使用此方法清除所有跟踪的实体
在创建新上下文实例的情况下可能很有用
不实用。