如何通过注入或UnitofWork将同一个dbcontext实例与多个服务一起使用?

时间:2018-12-22 20:19:54

标签: c# asp.net-mvc ninject dbcontext

我在互联网上发现了这种架构。我不知道这种架构的名称。如果是这样,请告诉我我的名字。

首先,我想解释一下这种体系结构如何能够轻松地从您那里获得关于我的问题的答案。

正如您在下面看到的,根据通常的体系结构,可能会有一层额外的层,称为接口。添加它是为了能够从WVC,WEB API等MVC之外的其他项目访问BLL层。

因此,这是最接近应用程序的层。

我在ninject注入中为每个实体编写了一些代码,如下所示:

kernel.Bind ()。To ();
kernel.Bind ()。To ();

当我在MVC控制器的构造函数方法中编写参数IUserService类型时,根据上述设置,Ninject触发并为该参数提供UserManager的实例,但是由于UserManager的构造方法需要根据设置的参数IUserDAL类型再次触发ninject并为其提供IUserDAL类型参数的EFUserRepository实例,这再次是因为EFUserRepository的构造函数需要一个参数SoleusContext类型,ninject被触发并为SoleusContext类型参数提供实例。

最后,我可以通过IUserService类型的参数到达DAL层 我可以使用MVC控制器来实现数据库处理。

但是我有这样的问题。当我将许多不同类型的Service引用(例如IUserService,IAddressService,IProductService)写入MVC控制器构造函数时,每个服务都使用SoleusContext的不同实例。我想在为每个请求定义Controller的构造函数的所有服务上使用相同的Context实例。

根据我的研究,可以通过为此架构创建通用的工作单元模式或在ninject上进行一些设置来实现。

我在Ninject上将SoleusContext绑定更新为InRequestScope()。所有服务都开始使用相同的SoleusContext实例工作,但是在项目的某些部分出现错误。我根据请求将User实例放入会话中。然后,当我尝试访问位于另一个请求的会话中的User实例上的Addresses List时。我得到这个错误。 “ ObjectContext实例已被处置,不能再用于需要连接的操作。”

如果有人告诉我如何在此体系结构上使用通用工作单元模式以及如何解决此问题,我将非常高兴。非常感谢。

MVC示例UserController

namespace Soleus.MvcUI.Controllers
{
   public class UserController : Controller
   {
        IUserService _userService;

        public UserController(IUserService userService)
        {
            _userService = userService;
        }
   }
}

=>实体层的基础实体

namespace Soleus.Entity
{
    public interface IEntity <TKey> where TKey : IEquatable<TKey>
    { 
        TKey Id { get; set; }
        DateTime CreatedDate { get; set; }
        string CreatedBy { get; set; }
        DateTime? ModifiedDate { get; set; }
        string ModifiedBy { get; set; }
        bool IsDeleted { get; set; }
    }
}

=>实体层的用户实体

namespace Soleus.Entity
{  
    public class User : IEntity<int>
    {
        public int Id { get; set; }
        public string UserName { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }
        public string PhoneNumber { get; set; }
        public  string Email { get; set; }
        public DateTime Birthday { get; set; }
        public DateTime CreatedDate { get; set; }
        public string CreatedBy { get; set; }
        public DateTime? ModifiedDate { get; set; }
        public string ModifiedBy { get; set; }
        public bool IsDeleted { get; set; }
        public virtual ICollection<Address> Addresses { get; set; }
     }
}

=>接口层的BaseService

namespace Soleus.Interface.Abstract
{
    [ServiceContract]
    public interface IService<TEntity,TKey> where TKey: IEquatable<TKey>
                                            where TEntity : class, IEntity<TKey>
    {

        [OperationContract]
        IQueryable<TEntity> GetAll();

        [OperationContract]
        IQueryable<TEntity> GetByCriteria(Expression<Func<TEntity, bool>> predicate);

        [OperationContract]
        TEntity GetById(TKey id);

        [OperationContract]
        void Create(TEntity entity);

        [OperationContract]
        void Delete(TEntity entity);

        [OperationContract]
        void Edit(TEntity entity);

        [OperationContract]
        void Activate(TEntity entity);

        [OperationContract]
        int Save();
    }
}

=>接口层的UserService

namespace Soleus.Interface.Abstract
{

    [ServiceContract]
    public interface IUserService : IService<User, int>
    {
        [OperationContract]
        User GetByUsername(string username);

        [OperationContract]
        User GetByEmail(string email);
    }
}

=> BLL层的基本管理器

namespace Soleus.BLL.Concrete
{
    public abstract class ManagerBase<TEntity,TKey> : IService<TEntity,TKey>   
                                                      where TKey: IEquatable<TKey> 
                                                      where TEntity : class, IEntity<TKey>

    {
        IDAL<TEntity,TKey> _DAL;

        public ManagerBase(IDAL<TEntity,TKey> DAL)
        {
            _DAL = DAL;
        }

        public IQueryable<TEntity> GetAll()
        {
            return _DAL.GetAll();
        }

        public IQueryable<TEntity> GetByCriteria(Expression<Func<TEntity, bool>> predicate)
        {
            return _DAL.GetByCriteria(predicate);
        }

        public TEntity GetById(TKey id)
        {
            return _DAL.GetById(id);
        }

        public void Create(TEntity entity)
        {
            _DAL.Create(entity);
        }

        public void Delete(TEntity entity)
        {
            _DAL.Delete(entity);
        }

        public void Edit(TEntity entity)
        {
            _DAL.Edit(entity);
        }

        public void Activate(TKey id, string modifiedBy = null)
        {
            _DAL.Activate(id, modifiedBy);
        }

        public int Save()
        {
            return _DAL.Save();
        }
    }
}

=> BLL层的用户管理器

namespace Soleus.BLL.Concrete
{
    public class UserManager : ManagerBase<User, int>, IUserService
    {
        IUserDAL _userDAL;

        public UserManager(IUserDAL userDAL) : base(userDAL)
        {
            _userDAL = userDAL;
        }

        public User GetByUsername(string username)
        {
            return _userDAL.GetByUsername(username);
        }

        public User GetByEmail(string email)
        {
            return _userDAL.GetByEmail(email);
        }
    }
}

=> DAL层的基本接口

namespace Soleus.DAL.Abstract
{
    public interface IDAL<TEntity,TKey>  where TKey : IEquatable<TKey>
                                         where TEntity : class, IEntity<TKey>
    {
        IQueryable<TEntity> GetAll();

        IQueryable<TEntity> GetByCriteria(Expression<Func<TEntity, bool>> predicate);

        TEntity GetById(TKey id);

        void Create(TEntity entity);

        void Delete(TEntity entity);

        void Edit(TEntity entity);

        void Activate(TEntity entity);

        int Save();

    }
}

=> DAL层的用户界面

namespace Soleus.DAL.Abstract
{ 
    public interface IUserDAL : IDAL<User, int>   
    {
        User GetByUsername(string username);

        User GetByEmail(string email);
    }
}

=> DAL层的基本存储库

namespace Soleus.DAL.Concrete
{
    public class EFRepositoryBase<TEntity,TKey> : IDAL<Tentity,TKey> 
                                                  where TKey:IEquatable<TKey>
                                                  where TEntity : class, IEntity<TKey>
    {

        protected readonly SoleusContext _context;

        public EFRepositoryBase(SoleusContext context)
        {
            _context = context;
        }

        public IQueryable<TEntity> GetAll()
        {
            return _context.Set<TEntity>().AsNoTracking();
        }

        public IQueryable<TEntity> GetByCriteria(Expression<Func<TEntity, bool>> predicate)
        {
            return _context.Set<TEntity().AsNoTracking().Where(predicate);
        }

        public TEntity GetById(TKey id)
        {
            return _context.Set<TEntity>().Find(id);
        }

        public void Create(TEntity entity)
        {
            entity.CreatedDate = DateTime.Now;
            _context.Set<TEntity>().Add(entity);
        }

        public void Delete(TEntity entity)
        {
            entity.IsDeleted = true;
            entity.ModifiedDate = DateTime.Now;
         }

         public void Edit(TEntity entity)
         {
             entity.ModifiedDate = DateTime.Now;
             _context.Entry(entity).State = EntityState.Modified;
         }

         public void Activate(TEntity entity)
         {
             entity.IsDeleted = false;
             entity.ModifiedDate = DateTime.Now;
         }

         public int Save()
         {
             return _context.SaveChanges();
         }
    }
}

=> DAL层的用户存储库

namespace Soleus.DAL.Concrete
{
    public class EFUserRepository: EFRepositoryBase<User, int>, IUserDAL
    {
        public User GetByUsername(string username)
        {
            return _context.Users.SingleOrDefault(i => i.UserName == username);
        }

        public User GetByEmail(string email)
        {
            return _context.Users.FirstOrDefault(i => i.Email == email);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

您的问题太广泛了……关于DbContext,将DbContext注入Web项目的正确方法是使用InRequestScope()

kernel.Bind<ISomeService>().To<SomeService>().InRequestScope();

确保您不要在不同的请求之间共享相同的dbContext ...并且不要担心性能:according to MS

  

DataContext是轻量级的,创建起来并不昂贵。典型的   LINQ to SQL应用程序在方法范围内创建DataContext实例   或作为代表逻辑集合的短期类的成员   相关的数据库操作。

另请参见Proper Session/DbContext lifecycle management


关于工作单元,关于这种模式有很多困惑,我看过一些教程,教如何使用DBContext实现UoW模式-他们没有意识到DbContext已经实现了UoW模式:{{3} }:

  

DbContext类

     

代表工作单元和存储库模式的组合   并允许您查询数据库并将更改分组在一起   然后将其作为一个单元写回到商店。 DbContext是   在概念上类似于ObjectContext。


关于会话,我看不到您如何向会话中添加值...并且由于您的问题已经太久了,因此建议您将其放在另一个问题中。但是,您需要记住,使用Session并不是线程安全的,并且有多种使用会话变量的方法(例如,将其存储在cookie中)