如何在ASP MVC中实现工作单元,存储库和业务逻辑?

时间:2021-02-14 14:32:15

I currently been assigned to a asp mvc project using entity framework. This will be a Line of Business application. I want to develop this app using repository and unit of work pattern. I'm new to this pattern (and new to .net too) and i am having a problem in understanding the pattern and how to implement it.

我目前被分配到使用实体框架的asp mvc项目。这将是一个业务线应用程序。我想使用存储库和工作单元模式开发此应用程序。我是这个模式的新手(也是.net的新手),我在理解模式以及如何实现它时遇到了问题。

I have read numerous articles and i think this is how my application should be

我读了很多文章,我认为这就是我的应用程序应该如何

Entity Framework -> Repository -> Unit of Work -> Client (Asp MVC)

实体框架 - >存储库 - >工作单元 - >客户端(Asp MVC)

I attach some code from this article http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

我附上了本文的一些代码http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in -an-ASP净MVC应用程序

using System;
using ContosoUniversity.Models;

namespace ContosoUniversity.DAL
{
    public class UnitOfWork : IDisposable
    {
        private SchoolContext context = new SchoolContext();
        private GenericRepository<Department> departmentRepository;
        private GenericRepository<Course> courseRepository;

        public GenericRepository<Department> DepartmentRepository
        {
            get
            {

                if (this.departmentRepository == null)
                {
                    this.departmentRepository = new GenericRepository<Department>(context);
                }
                return departmentRepository;
            }
        }

        public GenericRepository<Course> CourseRepository
        {
            get
            {

                if (this.courseRepository == null)
                {
                    this.courseRepository = new GenericRepository<Course>(context);
                }
                return courseRepository;
            }
        }

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

        private bool disposed = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    context.Dispose();
                }
            }
            this.disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }
}

Unit of Work will have repositories and will create DBContext upon creation

工作单元将具有存储库,并将在创建时创建DBContext

So controller will create Unit of Work upon creation. To Show data i will use this code

因此,控制器将在创建时创建工作单元。要显示数据,我将使用此代码

var department = UoW.departmentRepository.Find(1);
return View(department);

and when client click save button, i will run this code

当客户端单击“保存”按钮时,我将运行此代码

UoW.departmentRepository.Update(department);
UoW.Save();

My question:

  1. What if it takes hours from data retrieval until the client click save button. From what i know, we have to keep context as short as possible.

    如果从数据检索到客户端单击保存按钮需要数小时,该怎么办?据我所知,我们必须尽可能缩短背景。

  2. Where should i put business logic? Do i put it in repository? So i would call UoW.departmentRepository.Validate(department) before save. But then, what if i need to validate entity which relate to other entity. Do i call UoW.departmentRepository.Validate(course, department)?

    我应该把业务逻辑放在哪里?我把它放在存储库中吗?所以我会在保存前调用UoW.departmentRepository.Validate(部门)。但是,如果我需要验证与其他实体相关的实体,该怎么办?我是否打电话给UoW.departmentRepository.Validate(课程,部门)?

Is there a complete sample project for this kind of application?

是否有针对此类应用的完整示例项目?

EDIT

As Ant P adviced, i need to add another layer to put my business logic.

正如Ant P所建议的那样,我需要添加另一层来实现我的业务逻辑。

This is what i have come so far

这就是我到目前为止所得到的

Unit Of Work:

工作单位:

public class UnitOfWork : IDisposable
{
    private DBContext _context = new DBContext();

    public DBContext Context 
    {
      get 
      {
        return this._context;
      }
    }

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

    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                context.Dispose();
            }
        }
        this.disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

Business Logic:

public class SalesBusinessLogic : IDisposable
{
    private ICustomerRepository _customerRepo;
    private ISalesRepository _salesRepo;
    private UnitOfWork _uow;

    public SalesBusinessLogic(UnitOfWork uow)
    {
      this._uow = uow;
    }

    public ICustomerRepository CustomerRepo
    {
        get
        {

            if (this._customerRepo == null)
            {
                this._customerRepo = new CustomerRepository(this._uow);
            }
            return this._customerRepo;
        }
    }

    public ISalesRepository SalesRepo
    {
        get
        {

            if (this._salesRepo == null)
            {
                this._salesRepo = new SalesRepository(this._uow);
            }
            return this._salesRepo;
        }
    }

    public bool Validate(Sales sales)
    {
      //this is where validation performed
      return true;
    }
}

Controller:

public SalesController : Controller
{
    private UnitOfWork _uow = new UnitOfWork();
    private SalesBusinessLogic _bl = new SalesBusinessLogic(this._uow);

    public ActionResult Index()
    {
        var sales = _bl.SalesRepo.Find(1);
        sales.CustomerID = 1;
        if _bl.Validate(sales)
        {
          _bl.SalesRepo.Update(sales);
          _uow.Save();
        }
        return View(sales);
    }    
}

Here UnitOfWork act only as provider of dbcontext, which will be consumed by business logic and repository. Repository will be in BusinessLogic class.

这里UnitOfWork仅作为dbcontext的提供者,它将被业务逻辑和存储库使用。存储库将在BusinessLogic类中。

Server side validation will be handled by BusinessLogic and client side validation will be handled by viewmodel in Web Layer.

服务器端验证将由BusinessLogic处理,客户端验证将由Web Layer中的viewmodel处理。

My only concern is that dbcontext in UnitofWork is publicly accessible.

我唯一担心的是UnitofWork中的dbcontext是公共可访问的。

Am i in the right direction here?

我在这里朝着正确的方向吗?

1 个解决方案

#1


9  

What if it takes hours from data retrieval until the client click save button. From what i know, we have to keep context as short as possible.

如果从数据检索到客户端单击保存按钮需要数小时,该怎么办?据我所知,我们必须尽可能缩短背景。

This isn't an issue - the controller is instantiated per request. It doesn't persist while the user views the page. It sounds like you're misunderstanding at what point the controller is instantiated. When you instantiate the UnitOfWork within the controller's constructor, the process flow goes like this:

这不是问题 - 控制器是按请求实例化的。用户查看页面时,它不会保留。听起来你误解了控制器实例化的时间。在控制器的构造函数中实例化UnitOfWork时,流程如下所示:

  • The user issues a POST request (by clicking 'Save').
  • 用户发出POST请求(通过单击“保存”)。

  • The request reaches the server and the controller is instantiated (thereby instantiating the unit of work).
  • 请求到达服务器并且实例化控制器(从而实例化工作单元)。

  • The action method is called.
  • 调用action方法。

  • The unit of work is disposed.
  • 工作单位处理完毕。

Where should i put business logic? Do i put it in repository? So i would call UoW.departmentRepository.Validate(department) before save. But then, what if i need to validate entity which relate to other entity. Do i call UoW.departmentRepository.Validate(course, department)?

我应该把业务逻辑放在哪里?我把它放在存储库中吗?所以我会在保存前调用UoW.departmentRepository.Validate(部门)。但是,如果我需要验证与其他实体相关的实体,该怎么办?我是否打电话给UoW.departmentRepository.Validate(课程,部门)?

Typically, your business logic would be abstracted into a separate layer that sits between your web application and your repositories. Tutorials that show you repositories injected directly into controllers assume that you have "thin" business logic.

通常,您的业务逻辑将被抽象为位于Web应用程序和存储库之间的单独层。向您展示直接注入控制器的存储库的教程假设您具有“瘦”业务逻辑。

However, validation definitely isn't the job of a repository. You should create a separate view model for each view and validate those in your controller. The repository should be used pretty much solely for CRUD operations.

但是,验证肯定不是存储库的工作。您应该为每个视图创建一个单独的视图模型,并验证控制器中的视图模型。存储库应该仅用于CRUD操作。

#1


9  

What if it takes hours from data retrieval until the client click save button. From what i know, we have to keep context as short as possible.

如果从数据检索到客户端单击保存按钮需要数小时,该怎么办?据我所知,我们必须尽可能缩短背景。

This isn't an issue - the controller is instantiated per request. It doesn't persist while the user views the page. It sounds like you're misunderstanding at what point the controller is instantiated. When you instantiate the UnitOfWork within the controller's constructor, the process flow goes like this:

这不是问题 - 控制器是按请求实例化的。用户查看页面时,它不会保留。听起来你误解了控制器实例化的时间。在控制器的构造函数中实例化UnitOfWork时,流程如下所示:

  • The user issues a POST request (by clicking 'Save').
  • 用户发出POST请求(通过单击“保存”)。

  • The request reaches the server and the controller is instantiated (thereby instantiating the unit of work).
  • 请求到达服务器并且实例化控制器(从而实例化工作单元)。

  • The action method is called.
  • 调用action方法。

  • The unit of work is disposed.
  • 工作单位处理完毕。

Where should i put business logic? Do i put it in repository? So i would call UoW.departmentRepository.Validate(department) before save. But then, what if i need to validate entity which relate to other entity. Do i call UoW.departmentRepository.Validate(course, department)?

我应该把业务逻辑放在哪里?我把它放在存储库中吗?所以我会在保存前调用UoW.departmentRepository.Validate(部门)。但是,如果我需要验证与其他实体相关的实体,该怎么办?我是否打电话给UoW.departmentRepository.Validate(课程,部门)?

Typically, your business logic would be abstracted into a separate layer that sits between your web application and your repositories. Tutorials that show you repositories injected directly into controllers assume that you have "thin" business logic.

通常,您的业务逻辑将被抽象为位于Web应用程序和存储库之间的单独层。向您展示直接注入控制器的存储库的教程假设您具有“瘦”业务逻辑。

However, validation definitely isn't the job of a repository. You should create a separate view model for each view and validate those in your controller. The repository should be used pretty much solely for CRUD operations.

但是,验证肯定不是存储库的工作。您应该为每个视图创建一个单独的视图模型,并验证控制器中的视图模型。存储库应该仅用于CRUD操作。