已经处理了DbContext对象:如何防止对象被处理?

时间:2016-09-25 00:07:27

标签: c# .net asp.net-mvc dependency-injection unity-container

我正在使用asp.net mvc,Entityframework 6和Unity for DI场景。

我无法找到为什么我的DbContext对象过早处理。

我将GenericWoU类注入PeopleController类。当我调用ListPerson操作时,一切正常,但DbContext被释放。因此,如果我尝试编辑列表中的任何人,则会出现以下错误:

  

由于DbContext已经完成,因此无法完成操作   设置

如何防止DbContext这么早处理?

这是我的通用工作单元课程:

    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 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类:

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

1 个答案:

答案 0 :(得分:2)

一般问题是您的组件通过处置它来获取其依赖项的所有权。组件永远不知道它的依赖关系的生命周期是什么,以及它们以后是否可能被其他组件使用(甚至可能在同一请求中)。因此,这会使处置依赖关系变得危险(甚至是完全错误的)。

相反,作为一般经验法则,创建组件的人负责处理组件。因为在你的情况下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();
    }
}