DbContext 对象已被处置:如何防止对象被处置?
DbContext object has been disposed: how can I prevent the object to be disposed?
我在 DI 场景中使用 asp.net mvc、Entityframework 6 和 Unity。
我无法找出我的 DbContext 对象被过早处置的原因。
我将 GenericWoU class 注入 PeopleController
class。当我调用 ListPerson 操作时,一切正常,但 DbContext 已处理。因此,如果我尝试编辑列表中的任何人,则会出现以下错误:
The operation cannot be completed because the DbContext has been
disposed
如何防止 DbContext 过早被释放?
这是我的通用工作单元 class:
public class GenericUoW : IDisposable, IGenericUoW
{
private readonly DbContext entities = null;
public Dictionary<Type, object> repositories = new Dictionary<Type, object>();
public GenericUoW(DbContext entities)
{
this.entities = entities;
}
public IRepository<T> Repository<T>() where T : class
{
if (repositories.Keys.Contains(typeof(T)) == true)
{
return repositories[typeof(T)] as IRepository<T>;
}
IRepository<T> repo = new GenericRepository<T>(entities);
repositories.Add(typeof(T), repo);
return repo;
}
public void SaveChanges()
{
entities.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
entities.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
这是我的 GenericRepository
class:
class GenericRepository<T> : IRepository<T> where T : class
{
private readonly DbContext entities = null;
private DbSet<T> _objectSet;
public GenericRepository(DbContext _entities)
{
entities = _entities;
_objectSet = entities.Set<T>();
}
public IEnumerable<T> GetAll(Func<T, bool> predicate = null)
{
if (predicate != null)
{
return _objectSet.Where(predicate);
}
return _objectSet.AsEnumerable();
}
public T Get(Func<T, bool> predicate)
{
return _objectSet.First(predicate);
}
public void Add(T entity)
{
_objectSet.Add(entity);
}
public void Attach(T entity)
{
_objectSet.Attach(entity);
}
public void Delete(T entity)
{
_objectSet.Remove(entity);
}
}
这是我的 ContainerBootstrapper class:
public class ContainerBootstrapper
{
public static IUnityContainer Initialise()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
DbContext entities = new TeijonStuffEntities();
container.RegisterInstance(entities);
GenericUoW GUoW = new GenericUoW(entities);
container.RegisterInstance(GUoW);
MvcUnityContainer.Container = container;
return container;
}
}
普遍的问题是您的组件通过处置它来获取其依赖项的所有权。一个组件永远不知道它的依赖项的生命周期是多少,以及它们以后是否会被其他组件使用(甚至可能在同一个请求中)。所以这使得处理依赖关系变得危险(甚至是完全错误的)。
相反,根据一般经验,它是创建组件的人,负责处理组件。因为在你的情况下 Unity 创建了那个对象,它应该处理它(它会)。
这意味着您应该从 GenericUoW
中删除所有处置功能。这不仅是唯一正确的方法,而且实际上需要维护的代码要少得多,因为这不仅会影响 GenericUoW
,还会影响 GenericUoW
的所有可能的直接和间接消费者。在您的设计中,它们都必须实现 IDisposable
。正确应用 DI 时,您可以忽略它,这会对代码的可维护性产生巨大影响。
长话短说,将 GenericUoW
更改为以下内容:
public sealed class GenericUoW : IGenericUoW
{
private readonly Dictionary<Type, object> repositories =new Dictionary<Type, object>();
private readonly DbContext entities;
public GenericUoW(DbContext entities)
{
this.entities = entities;
}
public IRepository<T> Repository<T>() where T : class
{
if (!repositories.Keys.Contains(typeof(T))) {
IRepository<T> repo = new GenericRepository<T>(entities);
repositories.Add(typeof(T), repo);
}
return (IRepository<T>)repositories[typeof(T)];
}
public void SaveChanges() {
entities.SaveChanges();
}
}
我在 DI 场景中使用 asp.net mvc、Entityframework 6 和 Unity。
我无法找出我的 DbContext 对象被过早处置的原因。
我将 GenericWoU class 注入 PeopleController
class。当我调用 ListPerson 操作时,一切正常,但 DbContext 已处理。因此,如果我尝试编辑列表中的任何人,则会出现以下错误:
The operation cannot be completed because the DbContext has been disposed
如何防止 DbContext 过早被释放?
这是我的通用工作单元 class:
public class GenericUoW : IDisposable, IGenericUoW
{
private readonly DbContext entities = null;
public Dictionary<Type, object> repositories = new Dictionary<Type, object>();
public GenericUoW(DbContext entities)
{
this.entities = entities;
}
public IRepository<T> Repository<T>() where T : class
{
if (repositories.Keys.Contains(typeof(T)) == true)
{
return repositories[typeof(T)] as IRepository<T>;
}
IRepository<T> repo = new GenericRepository<T>(entities);
repositories.Add(typeof(T), repo);
return repo;
}
public void SaveChanges()
{
entities.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
entities.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
这是我的 GenericRepository
class:
class GenericRepository<T> : IRepository<T> where T : class
{
private readonly DbContext entities = null;
private DbSet<T> _objectSet;
public GenericRepository(DbContext _entities)
{
entities = _entities;
_objectSet = entities.Set<T>();
}
public IEnumerable<T> GetAll(Func<T, bool> predicate = null)
{
if (predicate != null)
{
return _objectSet.Where(predicate);
}
return _objectSet.AsEnumerable();
}
public T Get(Func<T, bool> predicate)
{
return _objectSet.First(predicate);
}
public void Add(T entity)
{
_objectSet.Add(entity);
}
public void Attach(T entity)
{
_objectSet.Attach(entity);
}
public void Delete(T entity)
{
_objectSet.Remove(entity);
}
}
这是我的 ContainerBootstrapper class:
public class ContainerBootstrapper
{
public static IUnityContainer Initialise()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
DbContext entities = new TeijonStuffEntities();
container.RegisterInstance(entities);
GenericUoW GUoW = new GenericUoW(entities);
container.RegisterInstance(GUoW);
MvcUnityContainer.Container = container;
return container;
}
}
普遍的问题是您的组件通过处置它来获取其依赖项的所有权。一个组件永远不知道它的依赖项的生命周期是多少,以及它们以后是否会被其他组件使用(甚至可能在同一个请求中)。所以这使得处理依赖关系变得危险(甚至是完全错误的)。
相反,根据一般经验,它是创建组件的人,负责处理组件。因为在你的情况下 Unity 创建了那个对象,它应该处理它(它会)。
这意味着您应该从 GenericUoW
中删除所有处置功能。这不仅是唯一正确的方法,而且实际上需要维护的代码要少得多,因为这不仅会影响 GenericUoW
,还会影响 GenericUoW
的所有可能的直接和间接消费者。在您的设计中,它们都必须实现 IDisposable
。正确应用 DI 时,您可以忽略它,这会对代码的可维护性产生巨大影响。
长话短说,将 GenericUoW
更改为以下内容:
public sealed class GenericUoW : IGenericUoW
{
private readonly Dictionary<Type, object> repositories =new Dictionary<Type, object>();
private readonly DbContext entities;
public GenericUoW(DbContext entities)
{
this.entities = entities;
}
public IRepository<T> Repository<T>() where T : class
{
if (!repositories.Keys.Contains(typeof(T))) {
IRepository<T> repo = new GenericRepository<T>(entities);
repositories.Add(typeof(T), repo);
}
return (IRepository<T>)repositories[typeof(T)];
}
public void SaveChanges() {
entities.SaveChanges();
}
}