我应该在哪里创建 ASP.Net MVC 3 应用程序中的工作单元实例? [英] Where should I create the Unit of Work instance in an ASP.Net MVC 3 application?

查看:30
本文介绍了我应该在哪里创建 ASP.Net MVC 3 应用程序中的工作单元实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了尽可能多的关于 Stackoverflow 的帖子,其中关于在其中使用工作单元模式一个包含业务层的 ASP.Net MVC 3 应用程序.但是,我仍然有几个问题关于这个主题,非常感谢人们可以给我的任何反馈.

I have read as many of the posts on Stackoverflow as I can find with regards the use of a Unit of Work pattern within an ASP.Net MVC 3 application which includes a Business Layer. However, I still have a couple of questions with regards this topic and would greatly appreciate any feedback people can give me.

我正在开发一个使用 EF 4.1 的 ASP.Net MVC 3 Web 应用程序.我将同时使用存储库和此项目的工作单元模式类似于它们在 这个很棒的教程

I am developing an ASP.Net MVC 3 Web application which uses EF 4.1. I will be using both the Repository and Unit of Work Patterns with this project similar to how they are used in this great tutorial

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

The difference in my project is that I need to also include a Business Layer (separate project in my solution) in order to carry out the various business rules for the application. The tutorial mentioned above does not have a Business layer, and therefore creates an instance of the Unit of Work class from the controller

public class CourseController : Controller
{
    private UnitOfWork unitOfWork = new UnitOfWork();

但是,我的问题是,如果我有业务层,我应该在哪里创建工作单元类的实例?

However, my question is, where should I create the instance of the Unit of Work class if I have a Business Layer?

我个人认为它应该在我的控制器中创建,然后像这样注入到业务层:

I personally think it should be created in my controller and then injected into the Business Layer like so:

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

我读过其他人说工作单元实例化不应在控制器中,而应在服务层中创建反而.我对这种方法不太确定的原因是因为我的 Controller 可能不得不使用几种不同的一个业务事务中的服务层,如果工作单元实例是在每个服务中创建的,它将导致多个正在创建工作单元实例,这违背了目的,即每个业务交易一个工作单元.

I have read others saying that the Unit of Work instantiation should not be in the Controller, but created in the Service Layer instead. The reason why I am not so sure about this approach is because my Controller may have to use several different Service Layers in one business transaction, and if the Unit of Work instance was created inside each Service, it would result in several Unit of Work instances being created, which defeats the purpose, ie, one Unit of Work per business transaction.

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

Maybe what I have explained above is wrong, but if so, I would greatly appreciate if someone could put me right.

再次感谢您的帮助.

推荐答案

我认为您需要进行一些更改:.

I think you have a couple of changes to make:.

  1. 允许您的 DI 容器在其构造函数中将 UnitOfWork 实例注入到您的服务类中,并将其完全保留在您的控制器之外.

  1. Allow your DI container to inject a UnitOfWork instance into your Service classes in their constructors, and leave it out of your Controller altogether.

如果您的 DI 容器支持(例如,Ninject 支持),请将您的 UnitOfWork 配置为基于每个请求进行管理;这样,您的服务将为每个请求传递一个不同的 UnitOfWork,然后就大功告成了.或者...

If your DI container supports it (Ninject does, for example), configure your UnitOfWork to be managed on a per-request basis; this way your services will be handed a distinct UnitOfWork for each request, and you're all done. Or...

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

If your DI container does not support per-request lifetimes, configure it to manage the UnitOfWork as a singleton, so every Service class gets the same instance. Then update your UnitOfWork to store its Entities object in a data store which stores objects on a per-request basis, for example in HttpContext.Current.Items, as described here.

编辑 1

关于UnitOfWork应该注入到哪里;我会说服务层是正确的地方.如果您将系统想象为一系列层,其中外层处理用户交互,下层处理数据存储,那么每一层都应该不那么关心用户,而更关心数据存储.UnitOfWork 是来自较低级别"层之一的概念,而 Controller 来自较高级别;您的 Service 层适合它们.因此,将 UnitOfWork 放入 Service 类而不是 Controller 是有意义的.

Regarding where the UnitOfWork should be injected; I'd say the Service layer is the correct place. If you imagine your system as a series of layers where the outer layers deal with user interactions and the lower layers deal with data storage, each layer should become less concerned with users and more concerned with data storage. UnitOfWork is a concept from one of the 'lower-level' layers and Controller is from a higher-level layer; your Service layer fits between them. It therefore makes sense to put the UnitOfWork into the Service class rather than the Controller.

编辑 2

详细说明UnitOfWork的创建及其与HttpContext.Current.Items的关系:

To elaborate on the UnitOfWork creation and it's relationship to HttpContext.Current.Items:

您的 UnitOfWork 将不再持有对 Entities 对象的引用,这将通过 HttpContext 对象完成,注入到 UnitOfWork 在这样的界面后面:

Your UnitOfWork would no longer hold a reference to an Entities object, that would be done through the HttpContext object, injected into the UnitOfWork behind an interface like this:

public interface IPerRequestDataStore : IDisposable
{
    bool Contains(string key);

    void Store<T>(string key, T value);

    T Get<T>(string key);
}

HttpContext 对象会像这样实现 IPerRequestDataStore:

The HttpContext object would then implement IPerRequestDataStore like this:

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

顺便说一句,我将其称为 StaticHttpContextPerRequestDataStore,因为它使用静态 HttpContext.Current 属性;这对于单元测试来说并不理想(完全是另一个主题),但至少名称表明了其依赖项的性质.

As an aside, I've called it StaticHttpContextPerRequestDataStore as it uses the static HttpContext.Current property; that's not ideal for unit testing (another topic altogether), but at least the name indicates the nature of its dependency.

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

Your UnitOfWork then passes the IPerRequestDataStore it's given to each of its Repository objects so they can access the Entities; this means that no matter how many UnitOfWork instances you create, you'll use the same Entities object throughout a request because it's stored and retrieved in the IPerRequestDataStore.

您将有一个抽象的基础 Repository,它将使用其 IPerRequestDataStore 延迟加载其 Entities 对象,如下所示:

You'd have an abstract base Repository which would use its IPerRequestDataStore to lazy-load its Entities object like this:

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

您的 PeopleRepository(例如)看起来像这样:

Your PeopleRepository (for example) would look like this:

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 的创建:

And finally, here's the creation of your PeopleController:

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

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

One of the central concepts here is that objects have their dependencies injected into them via their constructors; this is generally accepted as good practice, and more easily allows you to compose objects from other objects.

这篇关于我应该在哪里创建 ASP.Net MVC 3 应用程序中的工作单元实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆