簡體   English   中英

如何通過Injection或UnitofWork將同一個dbcontext實例與多個服務一起使用?

[英]How to use the same dbcontext instance with multiple services by Injection or UnitofWork?

我在互聯網上發現了這種架構。 我不知道這種架構的名稱。 如果是這樣,如果您告訴我名字,我會很高興。

首先,我想解釋一下該體系結構如何能夠輕松地從您那里得到關於我的問題的答案。

如下所示,根據通常的體系結構,可能會有一層稱為接口的額外層。 它被添加以能夠從MVC之外的其他項目(如WCF,WEB API)訪問BLL層。

因此,這是最接近應用程序的層。

我在ninject注入內部為每個實體編寫了一些代碼,如下所示:

kernel.Bind <IUserService>()。To <UserManager>();
kernel.Bind <IUserDAL>()。To <EFUserRepository>();

當我在MVC控制器的構造函數方法中編寫參數IUserService類型時,根據上述設置,Ninject觸發並為其提供了UserManager的實例,但是由於UserManager的構造函數方法需要參數IUserDAL類型,因此根據設置再次觸發ninject並再次為IUserDAL類型參數提供EFUserRepository實例,這是因為EFUserRepository的構造函數需要一個參數SoleusContext類型,並觸發ninject並為SoleusContext類型參數提供實例。

最后,我可以通過MVC控制器中的IUserService類型參數到達DAL層,並且可以實現數據庫處理。

但是我有這樣的問題。 當我將許多不同類型的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層的UserManager

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

您的問題太廣泛了……關於DbContext,將DbContext注入Web項目的正確方法是使用InRequestScope()

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

確保您在不同的請求之間不共享相同的dbContext ...並且不要擔心性能: 根據MS

DataContext是輕量級的,並且創建起來並不昂貴。 典型的LINQ to SQL應用程序在方法范圍內或作為表示相關數據庫操作的邏輯集的短期類的成員來創建DataContext實例。

另請參閱正確的會話/ DbContext生命周期管理


關於工作單元,關於這種模式有很多困惑,我看過一些教程,教如何使用DBContext實現UoW模式-他們沒有意識到DbContext已經實現了UoW模式: 根據MS

DbContext類

表示工作單元和存儲庫模式的組合,使您可以查詢數據庫並將更改分組在一起,然后將更改作為一個單元寫回到存儲中。 DbContext在概念上類似於ObjectContext。


關於會話,我看不到您如何向會話中添加值...並且由於您的問題已經太長了,因此建議您將其放在另一個問題中。 但是,請記住,使用Session並不是線程安全的,並且有多種使用Session變量的方法(例如,將其存儲在cookie中)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM