C# DbContext在C中的多层次IDisposable实现
基类:C# DbContext在C中的多层次IDisposable实现,c#,entity-framework,entity-framework-6,C#,Entity Framework,Entity Framework 6,基类: public abstract class Repository : IDisposable { private bool _disposed; private DbContext _context; public Repository(DbContext context) { _context = context; } public void SetSomething() { //...Acces
public abstract class Repository : IDisposable
{
private bool _disposed;
private DbContext _context;
public Repository(DbContext context)
{
_context = context;
}
public void SetSomething()
{
//...Access the database and set something for tracing
_context.Database.SqlQuery(....);
}
public void UnSetSomething()
{
//...Access the database and cancel something for tracing
_context.Database.SqlQuery(....);
}
#region Object Disposal
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~Repository()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
// free other managed objects that implement IDisposable only
if (_context != null)
{
_context.Dispose();
_context = null;
}
}
_disposed = true;
}
#endregion
}
子类:
public class ScheduleRepository : Repository
{
private AppContext _context;
public ScheduleRepository(DbContext context)
: base(context)
{
_context = (AppContext)context;
}
#region Object Disposal
bool _disposed;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~ScheduleRepository()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
// free other managed objects that implement IDisposable only
if (_context != null)
{
_context.Dispose();
_context = null;
}
}
_disposed = true;
base.Dispose(disposing);
}
#endregion
}
逻辑类:
public class ScheduleFacade
{
private ScheduleRepository _repository;
public ScheduleFacade()
{
_repository = new ScheduleRepository(AppContext.Create());
}
public ScheduleSetting GetScheduleById(string scheduleId)
{
if (!string.IsNullOrEmpty(scheduleId))
{
_repository.SetSomething();
ScheduleSetting settings = _repository.GetScheduleById(scheduleId);
_repository.UnSetSomething();
return LoadScheduleSettings(settings);
}
else
{
throw new ArgumentException("The scheduleId parameter cannot be empty.");
}
}
private ScheduleSetting LoadScheduleSettings(ScheduleSetting settings)
{
//...code ....
}
}
这是在抽象类实现上实现IDisposable的正确方法吗?这并没有像它应该遵循的那样遵循干巴巴的原则,但我不清楚如何正确地做到这一点
我想确保我正在适当地清理DbContext
编辑:似乎需要更多的信息来澄清我在做什么,以及为什么要在构造函数中传递DbContext。我在上面添加了更多的代码,请重新阅读。我需要抽象类中的DbContext来访问数据库并执行一些工作。这不是我将如何使用一个在多个子类之间共享的抽象类,从而允许我遵循DRY原则并集中未来的维护吗
如果我不通过contstructor方法注入将DbContext传递给abastract类,我该如何传递给它呢?但这需要未来存储库的开发人员可能忘记将该上下文传递给基类。如果您正在寻找通用的一次性抽象类,请查看下面的类,但是正如@Matthew和@dstanley所说的那样……存储库每次都应该初始化上下文
public abstract class DisposableObject : IDisposable
{
private bool _disposed = false;
public virtual bool IsDisposed
{
get { return _disposed; }
}
protected void CheckDisposed()
{
if (IsDisposed)
{
throw new ObjectDisposedException(this.GetType().FullName);
}
}
protected void CheckDisposed(string err)
{
if (IsDisposed)
{
throw new ObjectDisposedException(this.GetType().FullName, err);
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected void Dispose(bool disposing)
{
if (!_disposed)
{
OnDispose(disposing);
}
_disposed = true;
}
protected abstract void OnDispose(bool disposing); // this for the implementor to dispose their items
~DisposableObject()
{
Dispose(false);
}
}
对于存储库模式的实现,如下所示:
public abstract class Repository<T> : IDisposable where T : DbContext
{
private bool _disposed;
private T _context;
public Repository(T context)
{
_context = context;
}
protected T Context { get { return _context; } }
public void SetSomething()
{
//...Access the database and set something for tracing
// _context.Database.SqlQuery(....);
}
public void UnSetSomething()
{
//...Access the database and cancel something for tracing
//_context.Database.SqlQuery(....);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected void Dispose(bool disposing)
{
if (!_disposed)
{
if (_context != null)
{
_context.Dispose();
_context = null;
}
OnDispose(disposing);
}
_disposed = true;
}
// this for the implementor to dispose their items but not the context because it's already disposed from the base class
protected abstract void OnDispose(bool disposing);
~Repository()
{
Dispose(false);
}
}
所以它不依赖于EF为什么不让上下文受到保护,而不是在基类中有一个不同的字段?这样就不需要重写任何基类dispose函数。事实上,如果您现在没有覆盖它们,那么您是在隐藏它们。我不会暗示您的存储库上的IDisposable,因为您处理上下文的唯一内容不是由存储库创建的,而是提供给它的。并不是所有类都符合这一点,但一个好的做法是让创建一次性的东西成为处理它的对象。为了补充Matthew的正确观点,存储库不应该包含对上下文的引用,而应该为每个请求创建上下文,“所以,没有必要让您的存储库成为一次性的。”Matthew我已经更新了我的问题。请重新阅读。首先尝试使用泛型,公共抽象类Repository:IDisposable,其中T:DbContextYou确定关于此实现的另一个问题。在代码中使用basenew AppContext,然后使用this.Context.Schedules。我没有看到一个私有变量/字段包含您在ctor中实例化的.Context。你能解释一下吗?在基本存储库中,我有一个接受T的ctor,其中T:DBContext,为了在驱动类ScheduleRepository中使用这个上下文,我刚刚在存储库中创建了一个受保护的属性,以便访问上下文“受保护的T上下文{get return{U context;}”'我的意思是在子类中使用this.Context.Schedules。我看到您在ctor中为基类创建了一个新的AppContext,但是如何在子类中使用这个新实例化的上下文呢?我是否也需要在子类中创建新上下文?this.context.Schedules。。。将使用u在新AppContext中实例化的,因为它将从基类继承。。。顺便说一下,Schedules是我写的一个名称,您可能在AppContext类中有另一个属性名称,它引用DBAh中的Schedule表。我忘了继承权。
public class ScheduleRepository : Repository<AppContext>
{
public ScheduleRepository()
:base(new AppContext())
{
}
public Schedule GetById(int id) {
this.Context.Schedules. (....) // blah blah
}
protected override void OnDispose(bool disposing)
{
// if you are working with any thing that you must free it up
// do it here, but not the context
}
}
public class ScheduleFacade
{
private ScheduleRepository _repository;
public ScheduleFacade()
{
_repository = new ScheduleRepository();
}
public ScheduleSetting GetScheduleById(string scheduleId)
{
if (!string.IsNullOrEmpty(scheduleId))
{
_repository.SetSomething();
ScheduleSetting settings = _repository.GetScheduleById(scheduleId);
_repository.UnSetSomething();
return LoadScheduleSettings(settings);
}
else
{
throw new ArgumentException("The scheduleId parameter cannot be empty.");
}
}
private ScheduleSetting LoadScheduleSettings(ScheduleSetting settings)
{
//...code ....
}
}