Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 3 在ASP.NETMVC3应用程序中,我应该在哪里创建工作单元实例?_Asp.net Mvc 3_Architecture_Repository Pattern_Unit Of Work - Fatal编程技术网

Asp.net mvc 3 在ASP.NETMVC3应用程序中,我应该在哪里创建工作单元实例?

Asp.net mvc 3 在ASP.NETMVC3应用程序中,我应该在哪里创建工作单元实例?,asp.net-mvc-3,architecture,repository-pattern,unit-of-work,Asp.net Mvc 3,Architecture,Repository Pattern,Unit Of Work,我已经阅读了尽可能多的关于Stackoverflow的帖子,这些帖子都是关于在Stackoverflow中使用工作单元模式的 包含业务层的ASP.NETMVC3应用程序。不过,我还有几个问题要问 关于这个话题,如果有人能给我任何反馈,我将不胜感激 我正在开发一个ASP.NETMVC3Web应用程序,它使用EF4.1。我将同时使用存储库和 本项目的工作单元模式与本教程中使用的工作单元模式类似 我的项目的不同之处在于,我还需要包括一个业务层(解决方案中的单独项目),以便 执行应用程序的各种业务规则。

我已经阅读了尽可能多的关于Stackoverflow的帖子,这些帖子都是关于在Stackoverflow中使用工作单元模式的 包含业务层的ASP.NETMVC3应用程序。不过,我还有几个问题要问 关于这个话题,如果有人能给我任何反馈,我将不胜感激

我正在开发一个ASP.NETMVC3Web应用程序,它使用EF4.1。我将同时使用存储库和 本项目的工作单元模式与本教程中使用的工作单元模式类似

我的项目的不同之处在于,我还需要包括一个业务层(解决方案中的单独项目),以便 执行应用程序的各种业务规则。上面提到的教程没有业务层,并且 因此,从控制器创建工作类单元的实例

public class CourseController : Controller
{
    private UnitOfWork unitOfWork = new UnitOfWork();
然而,我的问题是,如果我有一个业务层,我应该在哪里创建工作单元类的实例

我个人认为它应该在我的控制器中创建,然后注入业务层,如下所示:

public class PeopleController : Controller
{
    private readonly IUnitOfWork _UoW;
    private IPersonService _personService;

    public PeopleController()
    {
        _UoW = new UnitOfWork();
        _personService = new PersonService(_UoW);
    }

    public PeopleController(IUnitOfWork UoW, IPersonService personService)
    {
        _UoW = UoW;
        _personService = personService;

    }

    public ActionResult Edit(int id)
    {
        Person person = _personService.Edit(id);
        return View(person);
    }

public class UnitOfWork : IUnitOfWork, IDisposable
{
    private BlogEntities _context = new BlogEntities();
    private PersonRepository personRepository = null;

    public IPersonRepository PersonRepository
    {
        get
        {

            if (this.personRepository == null)
            {
                this.personRepository = new PersonRepository(_context);
            }
            return personRepository;
        }
    }

    public void Save()
    {
        _context.SaveChanges();
    }


public class PersonService : IPersonService
{
    private readonly IUnitOfWork _UoW;

    public PersonService(IUnitOfWork UoW)
    {
        _UoW = UoW;
    }

    public Person Edit(int id)
    {
         Person person = _UoW.PersonRepository.GetPersonByID(id);
         return person;
    }

public class PersonRepository : IPersonRepository
{
    private readonly BlogEntities _context;

    public PersonRepository(BlogEntities context)
    {
        _context = context;
    }

    public Person GetPersonByID(int ID)
    {
        return _context.People.Where(p => p.ID == ID).Single();
    }
我读过其他人说工作单元实例化不应该在控制器中,而应该在服务层中创建 相反我不太确定这种方法的原因是因为我的控制器可能需要使用几种不同的方法 一个业务事务中的服务层,如果工作单元实例是在每个服务中创建的,则会产生多个服务层 正在创建的工作单元实例违背了目的,即每个业务事务一个工作单元

也许我上面解释的是错误的,但如果是这样的话,如果有人能纠正我的错误,我将不胜感激


再次感谢您的帮助。

我想您需要做一些更改:

  • 允许您的DI容器将一个
    UnitOfWork
    实例注入到其构造函数中的服务类中,并将其完全排除在控制器之外

  • 如果您的DI容器支持它(例如,Ninject支持),请将您的
    UnitOfWork
    配置为基于每个请求进行管理;这样,您的服务将为每个请求提供一个独特的
    工作单元
    ,您就完成了。或者

  • 如果您的DI容器不支持每个请求的生存期,请将其配置为将
    UnitOfWork
    作为一个单例进行管理,以便每个
    服务
    类都获得相同的实例。然后更新您的
    UnitOfWork
    以将其
    实体
    对象存储在数据存储中,该数据存储基于每个请求存储对象,例如在
    HttpContext.Current.Items
    中,如前所述

  • 编辑1

    关于应在何处注入
    工作单元
    ;我认为服务层是正确的位置。如果您将系统想象为一系列层,其中外层处理用户交互,下层处理数据存储,那么每一层都应该不再关注用户,而是更关注数据存储
    UnitOfWork
    是一个来自“较低级别”层之一的概念,控制器来自较高级别的层;您的
    服务
    层适合它们。因此,将
    工作单元
    放入
    服务
    类而不是
    控制器
    是有意义的

    编辑2

    要详细说明
    UnitOfWork
    创建及其与
    HttpContext.Current.Items
    的关系,请执行以下操作:

    您的
    UnitOfWork
    将不再持有对
    实体的引用,该引用将通过
    HttpContext
    对象完成,注入到如下界面后面的
    UnitOfWork
    中:

    public interface IPerRequestDataStore : IDisposable
    {
        bool Contains(string key);
    
        void Store<T>(string key, T value);
    
        T Get<T>(string key);
    }
    
    public class StaticHttpContextPerRequestDataStore : IPerRequestDataStore
    {
        public bool Contains(string key)
        {
            return HttpContext.Current.Items.Contains(key);
        }
    
        public void Store<T>(string key, T value)
        {
            HttpContext.Current.Items[key] = value;
        }
    
        public T Get<T>(string key)
        {
            if (!this.Contains(key))
            {
                return default(T);
            }
    
            return (T)HttpContext.Current.Items[key];
        }
    
        public void Dispose()
        {
            var disposables = HttpContext.Current.Items.Values.OfType<IDisposable>();
    
            foreach (var disposable in disposables)
            {
                disposable.Dispose();
            }
        }
    }
    
    public abstract class RepositoryBase : IDisposable
    {
        private readonly IPerRequestDataStore _dataStore;
    
        private PersonRepository personRepository;
    
        protected RepositoryBase(IPerRequestDataStore dataStore)
        {
            this._dataStore = dataStore;
        }
    
        protected BlogEntities Context
        {
            get
            {
                const string contextKey = "context";
    
                if (!this._dataStore.Contains(contextKey))
                {
                    this._dataStore.Store(contextKey, new BlogEntities());
                }
    
                return this._dataStore.Get<BlogEntities>(contextKey);
            }
        }
    
        public void Dispose()
        {
            this._dataStore.Dispose();
        }
    }
    
    public class PeopleRepository : RepositoryBase, IPersonRepository
    {
        public PeopleRepository(IPerRequestDataStore dataStore) 
            : base(dataStore)
        {
        }
    
        public Person FindById(int personId)
        {
            return this.Context.Persons.FirstOrDefault(p => p.PersonId == personId);
        }
    }
    
    另一方面,我将其命名为
    StaticHttpContextPerRequestDataStore
    ,因为它使用static
    HttpContext.Current
    属性;这对于单元测试来说并不理想(完全是另一个主题),但至少名称表明了其依赖性的性质

    然后,您的
    UnitOfWork
    IPerRequestDataStore
    传递给它的每个
    存储库
    对象,以便它们可以访问
    实体
    ;这意味着,无论您创建了多少个
    UnitOfWork
    实例,您都将在整个请求中使用相同的
    实体
    对象,因为它存储和检索在
    IPerRequestDataStore

    您将拥有一个抽象库
    存储库
    ,它将使用其
    IPerRequestDataStore
    延迟加载其
    实体
    对象,如下所示:

    public interface IPerRequestDataStore : IDisposable
    {
        bool Contains(string key);
    
        void Store<T>(string key, T value);
    
        T Get<T>(string key);
    }
    
    public class StaticHttpContextPerRequestDataStore : IPerRequestDataStore
    {
        public bool Contains(string key)
        {
            return HttpContext.Current.Items.Contains(key);
        }
    
        public void Store<T>(string key, T value)
        {
            HttpContext.Current.Items[key] = value;
        }
    
        public T Get<T>(string key)
        {
            if (!this.Contains(key))
            {
                return default(T);
            }
    
            return (T)HttpContext.Current.Items[key];
        }
    
        public void Dispose()
        {
            var disposables = HttpContext.Current.Items.Values.OfType<IDisposable>();
    
            foreach (var disposable in disposables)
            {
                disposable.Dispose();
            }
        }
    }
    
    public abstract class RepositoryBase : IDisposable
    {
        private readonly IPerRequestDataStore _dataStore;
    
        private PersonRepository personRepository;
    
        protected RepositoryBase(IPerRequestDataStore dataStore)
        {
            this._dataStore = dataStore;
        }
    
        protected BlogEntities Context
        {
            get
            {
                const string contextKey = "context";
    
                if (!this._dataStore.Contains(contextKey))
                {
                    this._dataStore.Store(contextKey, new BlogEntities());
                }
    
                return this._dataStore.Get<BlogEntities>(contextKey);
            }
        }
    
        public void Dispose()
        {
            this._dataStore.Dispose();
        }
    }
    
    public class PeopleRepository : RepositoryBase, IPersonRepository
    {
        public PeopleRepository(IPerRequestDataStore dataStore) 
            : base(dataStore)
        {
        }
    
        public Person FindById(int personId)
        {
            return this.Context.Persons.FirstOrDefault(p => p.PersonId == personId);
        }
    }
    
    最后,这里是您的
    PeopleController
    的创建:

    IPerRequestDataStore dataStore = new StaticHttpContextDataStore();
    UnitOfWork unitOfWork = new UnitOfWork(dataStore);
    PeopleService service = new PeopleService(unitOfWork);
    PeopleController controller = new PeopleController(service);
    

    这里的中心概念之一是,对象通过其构造函数将其依赖项注入其中;这通常被认为是一种良好的做法,并且更容易让您从其他对象合成对象。

    感谢您的帮助。目前,我从未使用或实现过DI容器,尽管我肯定不排除这种可能性。然而,对于我正在构建的这个应用程序,如果我选择不实现DI容器并继续使用手动DI,我在问题中提到的代码(特别是将UoW注入服务)是否仍然可以使用?您当然可以手动将所有内容插入到一起;在这种情况下,您必须使用创建对象的第二个选项,该对象使用
    HttpContext.Current.Items
    按请求存储实体对象。无论您是否使用容器,我仍然认为
    UnitOfWork
    应该进入服务层;我更新了我的答案来澄清这一点:)再次感谢史蒂夫,尽管我似乎越来越困惑了!您说我需要创建一个对象,该对象使用HttpContext.Current.Items在每个请求的基础上存储我的实体,但我的ObjectContext将存储/managi