gpt4 book ai didi

asp.net-mvc-3 - 我应该在哪里创建 ASP.Net MVC 3 应用程序中的 Unit of Work 实例?

转载 作者:行者123 更新时间:2023-12-04 00:48:06 26 4
gpt4 key购买 nike

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

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

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

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

但是,我的问题是,如果我有业务层,我应该在哪里创建 Unit of Work 类的实例?

我个人认为应该在我的 Controller 中创建它,然后像这样注入(inject)业务层:
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 中,而是在服务层中创建
反而。我不太确定这种方法的原因是因为我的 Controller 可能必须使用几种不同的
一个业务事务中的服务层,如果在每个服务中创建工作单元实例,则会导致多个
正在创建的工作单元实例,这违背了目的,即每个业务事务一个工作单元。

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

再次感谢您的帮助。

最佳答案

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

  • 允许您的 DI 容器注入(inject) UnitOfWork在构造函数中将实例添加到您的 Service 类中,并将其完全排除在您的 Controller 之外。
  • 如果您的 DI 容器支持它(例如 Ninject 支持),请配置您的 UnitOfWork按请求进行管理;这样,您的服务将获得独特的 UnitOfWork对于每个请求,您都完成了。或者...
  • 如果您的 DI 容器不支持每个请求的生命周期,请将其配置为管理 UnitOfWork作为单例,所以每个 Service类获得相同的实例。然后更新您的UnitOfWork存储其Entities数据存储中的对象,它基于每个请求存储对象,例如在 HttpContext.Current.Items 中,如 here 所述.

  • 编辑 1

    关于 UnitOfWork 的位置应该注入(inject);我会说服务层是正确的地方。如果您将系统想象成一系列层,其中外层处理用户交互,下层处理数据存储,那么每一层都应该更少关注用户,而更关注数据存储。 UnitOfWork是来自“较低级别”层之一的概念,而 Controller 来自较高级别;您的 Service层适合它们之间。因此,将 UnitOfWork进入 Service类而不是 Controller .

    编辑 2

    详述 UnitOfWork创作及其与 HttpContext.Current.Items 的关系:

    您的 UnitOfWork将不再包含对 Entities 的引用对象,这将通过 HttpContext对象,注入(inject) UnitOfWork在这样的界面后面:
    public interface IPerRequestDataStore : IDisposable
    {
    bool Contains(string key);

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

    T Get<T>(string key);
    }
    HttpContext然后对象将实现 IPerRequestDataStore像这样:
    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属性(property);这对于单元测试来说并不理想(完全是另一个主题),但至少名称表明了它的依赖性质。

    您的 UnitOfWork然后通过 IPerRequestDataStore它被分配给它的每一个 Repository对象,以便他们可以访问 Entities ;这意味着无论有多少 UnitOfWork您创建的实例,您将使用相同的 Entities整个请求中的对象,因为它在 IPerRequestDataStore 中存储和检索。 .

    你会有一个抽象的基础 Repository这将使用它的 IPerRequestDataStore延迟加载其 Entities像这样的对象:
    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 (例如)看起来像这样:
    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);

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

    关于asp.net-mvc-3 - 我应该在哪里创建 ASP.Net MVC 3 应用程序中的 Unit of Work 实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9115376/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com