为什么DbContext每次都在沾水?

时间:2014-07-21 07:11:32

标签: entity-framework wcf design-patterns castle-windsor

我正在使用Entity框架6和城堡windsor实现UOW和Generic存储库模式。我正在关注[http://blog.longle.net/2013/05/11/genericizing-the-unit-of-work-pattern-repository-pattern-with-entity-framework-in-mvc/][1]

链接

我的代码如下:

Conceptu.Core:

DataContext:

public interface IDataContext : IDisposable
    {
       IDbSet<TEntity> Set<TEntity>() where TEntity : class;
       int SaveChanges();
    }

域:

public interface IUnitOfWork : IDisposable
    {
        void Dispose();
        void Save();
        void Dispose(bool disposing);
        IRepository<TEntity> Repository<TEntity>() where TEntity : class;

    }


public interface IRepository<TEntity> where TEntity : class
    {

        TEntity Find(params object[] keyValues);
        int Insert(TEntity entity);
        IQueryable<TEntity> Queryable();
        IRepository<T> GetRepository<T>() where T : class;

    }

我在Conceptu.Data Layer中实现所有这些接口:

Conceptu.Data

EFUnitOFWork:

public class EFUnitOfWork : IUnitOfWork
    {
        #region Private variable

        private readonly IDataContext _dataContext;
        private bool _disposed;
        private Dictionary<string, object> _repositories;
        private ObjectContext _objectContext;
        private DbTransaction _transaction;

        #endregion Private variable

        public EFUnitOfWork(IDataContext context)
        {
            _dataContext = context;
        }

        public EFUnitOfWork()
        {
            _dataContext = new ConceptuModelContainer();
        }

     public void Save()
    {
      if (_disposed)
          throw new ObjectDisposedException("UnitOfWork");
      _dataContext.SaveChanges();
    }
        public void Dispose()
        {
            if (_objectContext != null && _objectContext.Connection.State ==                         ConnectionState.Open)
            {
                _objectContext.Connection.Close();
            }

            Dispose(true);
            GC.SuppressFinalize(this);
        }



        public void Dispose(bool disposing)
        {
            if (_disposed) return;
            if (disposing) _dataContext.Dispose();
            _disposed = true;
        }

        public IRepository<TEntity> Repository<TEntity>() where TEntity : class
        {

            if (_repositories == null)
            {
                _repositories = new Dictionary<string, object>();
            }

            var type = typeof(TEntity).Name;

            if (_repositories.ContainsKey(type))
            {
                return (IRepository<TEntity>)_repositories[type];
            }

            var repositoryType = typeof(Repository<>);
            try
            {
                _repositories.Add(type, Activator.CreateInstance(repositoryType.MakeGenericType(typeof(TEntity)), _dataContext, this));
            }
            catch (Exception er)
            {
                throw er;
            }
            return (IRepository<TEntity>)_repositories[type];


        }



    }
}

Repository.cs:

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
    {

        #region Private Fields
        private readonly IDataContext _dbContext;
        private readonly IDbSet<TEntity> _dbSet;
        private readonly IUnitOfWork _unitOfWork;
        #endregion Private Fields

        public Repository(IDataContext context, IUnitOfWork unitOfWork)
        {
            _dbContext = context;
            _dbSet = context.Set<TEntity>();
            _unitOfWork = unitOfWork;



        }
      public virtual int Insert(TEntity entity)
        {
            try
            {
                  _dbSet.Add(entity);
                return _dbContext.SaveChanges();
            }


            catch (Exception er)
            {

                var error = er.InnerException.InnerException as Exception;
                throw error;
            }


        }





        public IQueryable<TEntity> Queryable() { return _dbSet; }


        public IRepository<T> GetRepository<T>() where T : class
        {
            return _unitOfWork.Repository<T>();
        }

        internal IQueryable<TEntity> Select(
          Expression<Func<TEntity, bool>> filter = null,
          Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
          List<Expression<Func<TEntity, object>>> includes = null,
          int? page = null,
          int? pageSize = null)
        {
            IQueryable<TEntity> query = _dbSet;

            if (includes != null)
            {
                query = includes.Aggregate(query, (current, include) => current.Include(include));
            }
            if (orderBy != null)
            {
                query = orderBy(query);
            }
            if (filter != null)
            {
                query = query.AsExpandable().Where(filter);
            }
            if (page != null && pageSize != null)
            {
                query = query.Skip((page.Value - 1) * pageSize.Value).Take(pageSize.Value);
            }
            return query;
        }
    }

BootStrapper.cs

public class Bootstrapper
    {

       public static void Initialise()
       {
           IWindsorContainer _container = new WindsorContainer();
           _container.Kernel.Register(Component.For<IDataContext>().ImplementedBy<ConceptuModelContainer>());
           _container.Kernel.Register(Component.For<IUnitOfWork>().ImplementedBy<EFUnitOfWork>());
           //IoC.Container.Register(typeof(IDataContext), typeof(ConceptuModelContainer));
           //IoC.Container.Register(typeof(IUnitOfWork), typeof(EFUnitOfWork));


       }
    }

服务层:我是从wcf层调用它

我从服务层调用存储库

public class CompanyService : ICompanyService
    {
        #region Private fields
        private readonly IRepository<Company> _companyRepository;

        #endregion

        #region Constructor

        public CompanyService(IRepository<Company> companyRepository)
        {
            _companyRepository = companyRepository;
        }
       _companyRepository.Insert(_objcompany);

    }



[ServiceContract]
    public interface ICompanyService
    {
          [OperationContract]
         int SaveCompany(CompanyRequest _objCompanyRequest);
    }

在Global.asax.cs中,我写过注册

IWindsorContainer _container;

    protected void Application_Start(object sender, EventArgs e)
    {

        _container = new WindsorContainer();
        _container.AddFacility<WcfFacility>().Register(

            Component.For<IDataContext>().ImplementedBy<ConceptuModelContainer>().LifestylePerWebRequest(),
            Component.For<IUnitOfWork>().ImplementedBy<EFUnitOfWork>().LifestylePerWebRequest(),
            Component.For(typeof(IRepository<>)).ImplementedBy(typeof(Repository<>)).LifestylePerWebRequest(),

            Component.For<ICompanyService>().ImplementedBy<CompanyService>      ().Named("Conceptu.Services.CompanyService.CompanyService")
            );

    }

但我的问题是当我使用wcf服务调用Save时错误正在抛出。错误显示DBContext已被释放。

1 个答案:

答案 0 :(得分:2)

Component.For<IUnitOfWork>().ImplementedBy<EFUnitOfWork>().LifestylePerWebRequest()
  • 您通过工作单元处理每个请求的上下文,因为您已在IoC中注册它,即使您没有在UoW中明确处理它。为了证明你可以在dispose中放置一个断点,并在Castle调用Dispose时看到调用堆栈。
  • 您通过工厂将环境带到UoW。更好的方法是将已编译的模型存储在缓存中,这样就不会在每个请求中为上下文生成模型。

以下是模型商店的示例实现,您可以根据需要进行修改:

public class DefaultDbModelStore : IDbModelStore
{
    private readonly IDbModelBuilder _modelBuilder;
    private readonly Dictionary<string, IDbModel> _modelsDict;

    public DefaultDbModelStore(IDbModelBuilder modelBuilder)
    {
        _modelBuilder = modelBuilder;
        _modelsDict = new Dictionary<string, IDbModel>();
    }

    public IDbModel GetModel(string moduleName)
    {
        if (moduleName == null) { 
            moduleName = string.Empty; 
        }
        //TODO: Try using ReaderWriterLockSlim for improved performance
        lock (_modelsDict)
        {
            IDbModel result;
            if (!_modelsDict.TryGetValue(moduleName, out result))
            {
                result = _modelBuilder.BuildModel(moduleName);
                _modelsDict.Add(moduleName, result);
            }
            return result;
        }
    }
}

有一个DbContext的构造函数,它接受已编译的模型。