Как использовать один и тот же экземпляр dbcontext с несколькими службами Injection или UnitofWork? - PullRequest
0 голосов
/ 22 декабря 2018

Я обнаружил эту архитектуру в интернете.Я не знаю, есть ли название этой архитектуры или нет.Если это так, я буду рад, если вы скажете мне имя.

Во-первых, я хочу объяснить, как работает эта архитектура, чтобы можно было легко получить от вас ответ на мой вопрос.

Каквы видите ниже, может быть один дополнительный уровень, который называется интерфейсом в соответствии с обычной архитектурой.Он был добавлен, чтобы иметь возможность достигать BLL Layer из других проектов, кроме MVC, таких как WCF, а также WEB API.

Итак, это самый близкий уровень к приложениям.

Я написал несколько кодов внутри инъекции объекта для каждой сущности, как показано ниже для пользователя

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

Когда я записываю тип параметра IUserService в методе конструктора контроллера MVC, в соответствии с приведенными выше настройками срабатывает Ninject, и для этого параметра создается экземпляр UserManagerно поскольку метод конструктора UserManager ожидает тип параметра IUserDAL, в соответствии с параметрами настройки запускается снова и он дает экземпляр EFUserRepository для параметра типа IUserDAL, опять же, потому что конструктор EFUserRepository ожидает параметр типа SoleusContext, а затем запускается экземпляр класса и параметр типа SoleusContext.

Наконец, я могу достичь уровня DAL по параметру типа IUserService в контроллере MVC и реализовать процесс базы данных.

Но у меня есть такая проблема.Когда я записываю много ссылок на службы различных типов в конструктор контроллера MVC, например IUserService, IAddressService, IProductService, каждая служба использует свой экземпляр SoleusContext.Я хочу использовать один и тот же экземпляр Context во всех сервисах, который определяется конструктором Controller для каждого запроса.

Согласно моим исследованиям, это возможно, если создать общий шаблон unitofwork для этой архитектуры или выполнить некоторые настройки на ninject.

Я обновил привязку SoleusContext как InRequestScope () для Ninject.все сервисы начали работать с одним экземпляром SoleusContext, но я получаю сообщение об ошибке в какой-то части проекта.Я поместил пользовательский экземпляр в сеанс по запросу.Затем, когда я попытался добраться до списка адресов, который находится на экземпляре пользователя в сеансе по другому запросу.Я получаю эту ошибку.«Экземпляр 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 of => Интерфейсный уровень

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 of => Интерфейсный уровень

namespace Soleus.Interface.Abstract
{

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

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

Базовый менеджер => BLL Layer

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

UserManager => BLL Layer

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 Layer

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 Layer

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 голосов
/ 23 декабря 2018

Ваш вопрос слишком широкий ... относительно DbContext, правильный способ добавить DbContext в веб-проект, это с InRequestScope():

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

Убедитесь, что вы не делитесьодин и тот же dbContext среди разных запросов ... и не беспокойтесь о производительности: в соответствии с MS :

DataContext является легким и недорогим в создании.Типичное приложение LINQ to SQL создает экземпляры DataContext в области действия метода или в качестве члена недолговечных классов, представляющих логический набор связанных операций с базой данных.

См. Также Правильный жизненный цикл сеанса / DbContext.management


Относительно единицы работы, существует много путаницы вокруг этого шаблона, и я видел несколько учебных пособий, в которых рассказывается, как реализовать шаблон UoW с использованием DBContext - но они не понимают, чтоDbContext уже реализует шаблон UoW: в соответствии с MS :

DbContext Class

Представляет комбинацию шаблонов Unit-Of-Work и Repository и позволяет вамзапросить базу данных и сгруппировать изменения, которые затем будут записаны обратно в хранилище как единое целое.DbContext концептуально похож на ObjectContext.


Что касается сеанса, я не вижу, как вы добавляете значения в сеанс ... и поскольку ваш вопрос уже слишком длинный, я рекомендуюпоставив это в другом вопросе.Однако вы должны помнить, что использование Session не является потокобезопасным, и существуют разные подходы к использованию переменных сеанса (например, их хранение в cookie)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...