简体   繁体   English

存储库中或单独的业务类中的业务逻辑?

[英]Business logic in repositories or in separate business classes?

I'm developing an application where I'm using repositories (repository pattern) that handle all the CRUD operations (I'm using entity framework) and Unit of work for handling the context. 我正在开发一个应用程序,其中我使用存储库(存储库模式)来处理所有CRUD操作(我使用实体框架)和工作单元来处理上下文。 I have a generic repository like this: 我有一个像这样的通用存储库:

Public Interface IRepository(Of TEntity As Class)

 Function GetAll() As IEnumerable(Of TEntity)
 Function GetByID(id As Object) As TEntity

End Interface


Public Class Repository(Of TEntity As Class)
  Implements IRepository(Of TEntity)

  Friend _dbContext As Entities = Nothing
  Friend _dbSet As IDbSet(Of TEntity)

  Public Sub New(ByVal context As Entities)
    If context Is Nothing Then
        Throw New ArgumentNullException("context wasn't supplied")
    End If
    Me._dbContext = context
    Me._dbSet = context.Set(Of TEntity)()
  End Sub

  Public Function GetAll() As IEnumerable(Of TEntity) Implements IRepository(Of TEntity).GetAll
    Return _dbSet.ToList().AsQueryable()
 End Function



 Public Overridable Function GetByID(id As Object) As TEntity Implements IRepository(Of     
    TEntity).GetByID
    Return _dbSet.Find(id)
 End Function


End Class


Public Interface IUnitOfWork

  ReadOnly Property PersonRepository() As IRepository(Of Person)
  ReadOnly Property OrgRepository() As IRepository(Of Organization)

  Sub Save()

End Interface


Public Class UnitOfWork
Implements IUnitOfWork
Implements IDisposable

Private _context As Entities
Private _personRepository As IRepository(Of Person)
Private _orgRepository As IRepository(Of Organization)
Private disposed As Boolean = False

Public Sub New()
    Me._context = New Entities
End Sub

Public ReadOnly Property PersonRepository() As IRepository(Of Person) Implements  IUnitOfWork.PersonRepository
    Get
        If Me._personRepository Is Nothing Then
            Me._personRepository = New Repository(Of Person)(_context)
        End If
        Return _personRepository
    End Get
End Property

.
.
.
.

Public Sub Save() Implements IUnitOfWork.Save
    _context.SaveChanges()
End Sub

Public Sub Dispose() Implements IDisposable.Dispose
    Dispose(True)
    GC.SuppressFinalize(Me)
End Sub

Protected Overridable Sub Dispose(disposing As Boolean)
    If Not Me.disposed Then
        If disposing Then
            _context.Dispose()
        End If
    End If
    Me.disposed = True
End Sub

End Class

My problem is the business logic, where should I put it? 我的问题是业务逻辑,应该放在哪里? I need to count up all my persons returned and I have to calculate the total weight of all these persons. 我需要计算返回的所有人员,并且必须计算所有这些人员的总体重。 Should this be done in the person repository or do I need a separate person class for this? 应该在人员存储库中完成此操作还是为此需要单独的人员类别? This is not a MVC application, my classes should be used by another application (I have no front end classes). 这不是MVC应用程序,我的类应该由另一个应用程序使用(我没有前端类)。

I have looked at this example 我看了这个例子

Under the headline “Changing the Course Controller to use the UnitOfWork Class and Repositories” he does this 在“更改课程负责人以使用UnitOfWork类和存储库”标题下,他这样做

public ViewResult Details(int id) { 
  Course course = unitOfWork.CourseRepository.GetByID(id); 
  return View(course); 
 } 

How is it possible to say 怎么说呢

Course course = unitOfWork.CourseRepository.GetByID(id);

The course object is of type Course but the object returned from unitOfWork.CourseRepository.GetByID(id) is of type course entity (from entity framework). 课程对象是课程类型,但是从unitOfWork.CourseRepository.GetByID(id)返回的对象是课程实体类型(来自实体框架)。

My last question….can I have any properties in the repository classes. 我的最后一个问题…。我可以在存储库类中具有任何属性吗? If I should have my function for counting all the people and my total weight function in the repository class I need to also have my properties for name, address and so on for storing information. 如果我应该在存储库类中具有用于统计所有人员的功能和总重量函数,则还需要具有用于存储信息的名称,地址等属性。

I hope sombody can help me :) 我希望有人可以帮助我:)

Thanks in advance! 提前致谢!

Liss 丽丝

EDIT: 编辑:

Thanks for your answer! 感谢您的回答! So what you are saying is that if I don't have any heavy logic (that is the case for me) I use an extra Person class where I have my properties an also functions for weight and total number of person, but also functions that "mirrors" the functions (GetAll, GetByID) in the generic repository class. 因此,您要说的是,如果我没有任何繁琐的逻辑(对我来说就是这种情况),那么我将使用一个额外的Person类,该类具有我的属性,并且还可以计算体重和人数,还可以“镜像”通用存储库类中的功能(GetAll,GetByID)。 And I use the Person class from other classes not the repository class? 我使用其他类中的Person类而不是存储库类? I still don't understand the example Course course = unitOfWork.CourseRepository.GetByID(id), her the repository and unit of work is used the same way as I did, I think. 我仍然不理解示例课程Course = unitOfWork.CourseRepository.GetByID(id),我认为她的存储库和工作单元的使用方式与我相同。 But when I try this, the unitOfWork.CourseRepository.GetByID(id) returns an object of entity type but the course is an "ordinary" object type (a ordinary class with only properties). 但是,当我尝试这种方法时,unitOfWork.CourseRepository.GetByID(id)返回一个实体类型的对象,但是过程是一个“普通”对象类型(一个只有属性的普通类)。 How can I say: object of type A = object of type B? 我怎么说:A型对象= B型对象?

EDIT 2: 编辑2:

Thanks a lot for taking the time to answer me!! 非常感谢您抽出宝贵的时间回答我! So what you say is that it is sometimes better to not auto generate entities but write POCO class instead? 那么您说的是,有时最好不要自动生成实体,而改写POCO类呢? But if I want to use my auto generated entities, and I have an entity named PersonEntity I can use this like this in my controller class like this: 但是,如果我想使用自动生成的实体,并且有一个名为PersonEntity的实体,则可以在控制器类中使用以下形式:

 Dim personEntity As PersonEntity

 personEntity = unitOfWork.PersonEntityRepository.GetByID(id)

But if I do it like this I have a reference to an entity in my controller class, but do I want that? 但是,如果我这样做,就可以在我的控制器类中引用一个实体,但是我想要吗? Isn't it best to separate the entities from the controller if I later need to change from Entity Framework? 如果以后需要从Entity Framework进行更改,最好将实体与控制器分开吗? But what I still do not understand is, should I create a new Person class with the same properties as the autogen PersonEntity class and use this in my controller like this 但是我仍然不明白的是,我应该创建一个具有与autogen PersonEntity类相同属性的新Person类,并在我的控制器中像这样使用它

Dim person As Person

person = unitOfWork.PersonEntityRepository.GetByID(id)

But then the unitOfWork.PersonEntityRepository.GetByID(id) will return a object of type PersonEntity… so this is not working. 但是然后unitOfWork.PersonEntityRepository.GetByID(id)将返回一个PersonEntity类型的对象……所以这是行不通的。 And where should I put my total weight and total persons functions? 我应该把我的总体重和总人数放在哪里?

If I understand what you are saying, an entity object can be used as a transfer object but it's better to use a POCO/DTO object. 如果我理解您的意思,则可以将实体对象用作传输对象,但最好使用POCO / DTO对象。 But if I use a Person POCO can I still have the PersonEntity object? 但是,如果我使用Person POCO,我仍然可以拥有PersonEntity对象吗? And how do I populate the POCO object when I return the PersonEntity object? 当我返回PersonEntity对象时,如何填充POCO对象?

Regarding "where should I put business logic": There are two approaches: 关于“我应该在哪里放置业务逻辑”:有两种方法:

  1. Complex business logic usually goes into a service layer. 复杂的业务逻辑通常进入服务层。 A service may depend on one or more repositories to perform CRUD operations on your models. 一项服务可能取决于一个或多个存储库以对模型执行CRUD操作。 Thus a single service operation representing a business operation may depend on multiple simple operations. 因此,代表业务操作的单个服务操作可能依赖于多个简单操作。 Then you could reuse this service layer in your controllers and other applications. 然后,您可以在控制器和其他应用程序中重用此服务层。 Use basic POCO/DTOs for data transfer between layers. 使用基本的POCO / DTO在层之间进行数据传输。

  2. Use domain entities which contain their own operation logic. 使用包含其自身操作逻辑的域实体。

A similar discussion can be found here so please have a look on: Repository pattern and/or/vs business logic layer 在这里可以找到类似的讨论,因此请看一下: 存储库模式和/或/ vs业务逻辑层

And about the example you mentioned which is using 关于您提到的正在使用的示例

"Course course = unitOfWork.CourseRepository.GetByID(id);"

It is very possible as we can compose the Repository and UoW Patterns in different ways. 因为我们可以用不同的方式组合存储库和UoW模式,所以这很有可能。 Please have a look on this question https://softwareengineering.stackexchange.com/questions/151374/relationship-between-repository-and-unit-of-work 请看一下这个问题https://softwareengineering.stackexchange.com/questions/151374/relationship-between-repository-and-unit-of-work

and an answer by Wouter de Kort here Entity Framework + Repository + Unit of Work 以及Wouter de Kort的回答这里实体框架+存储库+工作单元

Yes, you can have properties instead of get methods. 是的,您可以拥有属性而不是get方法。 I prefer get methods as it gives better uniformity to use a repository. 我更喜欢get方法,因为它可以更好地统一使用存储库。

Hope it would be helpful. 希望对您有所帮助。 Please let me know in case of further questions. 如有其他问题,请让我知道。 Thanks. 谢谢。

Additional Answers after your edit: 编辑后的其他答案:

You are Welcome. 别客气。 I have downloaded that code for the example and looked again to understand your query but I can see that: both side of the line :"Course course = unitOfWork.CourseRepository.GetByID(id);" 我已经为示例下载了该代码,并再次查看以了解您的查询,但是我可以看到:行的两侧:“课程= unitOfWork.CourseRepository.GetByID(id);” refers to same class :ContosoUniversity.Models.Course. 指的是同一类:ContosoUniversity.Models.Course。

 public ActionResult Edit(int id)
    {
        Course course = unitOfWork.CourseRepository.GetByID(id);
        PopulateDepartmentsDropDownList(course.DepartmentID);
        return View(course);
    }

The code inside following "Details" method of CourseController does not have the same code as shown in the webpage: public ActionResult Details(int id) CourseController的“ Details”方法后面的代码与网页中显示的代码不同:public ActionResult Details(int id)

Further you can have Person class as a Model class having business logic related to Person inside class. 此外,您可以将Person类作为具有与Person内部类相关的业务逻辑的Model类。 And PersonRepository would have methods like (GetAll, GetByID). 而且PersonRepository将具有(GetAll,GetByID)之类的方法。 If you have many repositories you can create a GenericRepository too as given below: 如果您有许多存储库,则也可以如下所示创建GenericRepository:

class GenericRepository<TEntity> where TEntity : class

I hope its fine by now. 我希望现在可以。 Further questions are most welcome. 欢迎进一步的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM