【问题标题】:Business logic in repositories or in separate business classes?存储库或单独的业务类中的业务逻辑?
【发布时间】:2013-07-05 12:22:09
【问题描述】:

我正在开发一个应用程序,其中我使用存储库(存储库模式)来处理所有 CRUD 操作(我正在使用实体框架)和用于处理上下文的工作单元。 我有一个像这样的通用存储库:

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

我的问题是业务逻辑,我应该把它放在哪里?我需要计算所有返回的人,我必须计算所有这些人的总重量。这应该在人员存储库中完成还是我需要一个单独的人员类? 这不是 MVC 应用程序,我的类应该由另一个应用程序使用(我没有前端类)。

我看过this example

在标题“更改课程控制器以使用 UnitOfWork 类和存储库”下,他这样做了

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

怎么说呢

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

课程对象是 Course 类型,但从 unitOfWork.CourseRepository.GetByID(id) 返回的对象是课程实体类型(来自实体框架)。

我的最后一个问题……我可以在存储库类中有任何属性吗?如果我应该在存储库类中拥有统计所有人的功能和总权重功能,我还需要拥有用于存储信息的姓名、地址等属性。

希望有人能帮帮我:)

提前致谢!

利斯

编辑:

感谢您的回答!所以你的意思是,如果我没有任何繁重的逻辑(对我来说就是这种情况),我会使用一个额外的 Person 类,其中我有我的属性,还有体重和总人数的函数,但也有函数“镜像”通用存储库类中的函数(GetAll、GetByID)。我使用来自其他类的 Person 类而不是存储库类?我仍然不明白示例 Course course = unitOfWork.CourseRepository.GetByID(id),我认为她的存储库和工作单元的使用方式与我相同。但是当我尝试这个时, unitOfWork.CourseRepository.GetByID(id) 返回一个实体类型的对象,但课程是一个“普通”对象类型(一个只有属性的普通类)。怎么说:A 类型的对象 = B 类型的对象?

编辑 2:

非常感谢您花时间回答我!所以你说的是有时最好不要自动生成实体而是编写 POCO 类?但是,如果我想使用自动生成的实体,并且我有一个名为 PersonEntity 的实体,我可以在我的控制器类中像这样使用它:

 Dim personEntity As PersonEntity

 personEntity = unitOfWork.PersonEntityRepository.GetByID(id)

但是如果我这样做,我在我的控制器类中引用了一个实体,但我想要那个吗?如果我以后需要从 Entity Framework 进行更改,是否最好将实体与控制器分开? 但我仍然不明白的是,我是否应该创建一个与 autogen PersonEntity 类具有相同属性的新 Person 类并像这样在我的控制器中使用它

Dim person As Person

person = unitOfWork.PersonEntityRepository.GetByID(id)

但是 unitOfWork.PersonEntityRepository.GetByID(id) 将返回一个 PersonEntity 类型的对象......所以这不起作用。 我应该把我的总重量和总人数函数放在哪里?

如果我理解您的意思,实体对象可以用作传输对象,但最好使用 POCO/DTO 对象。但是,如果我使用 Person POCO,我还能拥有 PersonEntity 对象吗?以及当我返回 PersonEntity 对象时如何填充 POCO 对象?

【问题讨论】:

    标签: architecture repository-pattern unit-of-work business-logic


    【解决方案1】:

    关于“我应该把业务逻辑放在哪里”:有两种方法:

    1. 复杂的业务逻辑通常进入服务层。一项服务可能依赖一个或多个存储库来对您的模型执行 CRUD 操作。因此,代表一个业务操作的单个服务操作可能依赖于多个简单操作。然后你可以在你的控制器和其他应用程序中重用这个服务层。使用基本的 POCO/DTO 在层之间传输数据。

    2. 使用包含自己操作逻辑的域实体。

    可以在此处找到类似的讨论,因此请查看: Repository pattern and/or/vs business logic layer

    关于你提到的使用的例子

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

    这是很有可能的,因为我们可以以不同的方式组合存储库和 UoW 模式。请看一下 这个问题https://softwareengineering.stackexchange.com/questions/151374/relationship-between-repository-and-unit-of-work

    这里是 Wouter de Kort 的回答 Entity Framework + Repository + Unit of Work

    是的,您可以使用属性而不是 get 方法。我更喜欢 get 方法,因为它可以更好地统一使用存储库。

    希望对您有所帮助。如果有其他问题,请告诉我。谢谢。

    编辑后的其他答案:

    不客气。我已经下载了该示例的代码并再次查看以了解您的查询,但我可以看到:行的两侧:“Course course = unitOfWork.CourseRepository.GetByID(id);”指同一类:ContosoUniversity.Models.Course。

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

    CourseController 的“Details”方法后面的代码与网页显示的代码不同: 公共 ActionResult 详细信息(int id)

    您还可以将 Person 类作为 Model 类,在类内部具有与 Person 相关的业务逻辑。并且 PersonRepository 将具有 (GetAll, GetByID) 之类的方法。如果您有许多存储库,您也可以创建一个 GenericRepository,如下所示:

    class GenericRepository<TEntity> where TEntity : class
    

    我希望现在一切都好。欢迎进一步提问。

    【讨论】:

    • 感谢您的快速回答!我已经编辑了我的帖子,你有时间看看吗?!
    • 我已经下载了示例页面的代码并再次查看以了解您的查询,但我可以看到:行的两侧:“Course course = unitOfWork.CourseRepository.GetByID(id);”指同一类:ContosoUniversity.Models.Course。我无法通过编写“我怎么能说:A 类型的对象 = B 类型的对象?”来理解你所指的内容?在您最近的编辑中。
    • 我还编辑了我的答案,其中包括上方评论中的消息。谢谢。
    • 再次感谢。 Course、Department、Instructor..... 类与我从 Entity 框架自动生成的 Person 和 Organization 类相同吗?抱歉,但我忘了说我正在使用 EF 并且在顶部有自动生成的类和通用存储库。我是否需要 autogen 实体类和一个通用存储库类,以及另一个 personservice/普通人类?我觉得课程太多了……我无法理解所有这些是如何结合在一起的。抱歉,希望问题不要太多!
    • 我喜欢提出更多问题。谢谢。无需创建新类,因为您可以扩展生成的 EF 类。请查看msdn.microsoft.com/en-us/library/aa697427%28v=vs.80%29.aspx。此页面说:“ADO.NET 实体框架包含一个工具,给定 EDM 模式,它将生成代表 .NET 环境中 EDM 实体的 .NET 类。生成的类是部分类,因此可以扩展它们在单独的文件中使用自定义业务逻辑,而不会干扰代码生成器。”
    猜你喜欢
    • 1970-01-01
    • 2012-11-07
    • 2011-03-29
    • 2011-05-28
    • 1970-01-01
    • 2010-12-14
    • 2015-06-30
    • 2011-09-23
    • 2010-12-24
    相关资源
    最近更新 更多