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

时间:2013-07-08 08:28:04

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

我正在开发一个应用程序,我正在使用处理所有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);

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

我的上一个问题......我可以在存储库类中拥有任何属性。如果我应该有我的函数来计算存储库类中的所有人和我的总权重函数,我还需要具有名称,地址等属性来存储信息。

我希望sombody可以帮助我:)。

提前致谢!

利斯

编辑:

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

编辑2:

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

 Dim personEntity As PersonEntity

 personEntity = unitOfWork.PersonEntityRepository.GetByID(id)

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

Dim person As Person

person = unitOfWork.PersonEntityRepository.GetByID(id)

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

如果我理解你在说什么,实体对象可以用作转移对象,但最好使用POCO / DTO对象。但是如果我使用Person POCO,我还能拥有PersonEntity对象吗?当我返回PersonEntity对象时,如何填充POCO对象?

1 个答案:

答案 0 :(得分:0)

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

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

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

  3. 此处可以找到类似的讨论,请查看: 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方法。我更喜欢使用方法,因为它可以更好地统一使用存储库。

    希望它会有所帮助。如有其他问题,请告诉我。感谢。

    修改后的其他答案:

    欢迎你。我已经下载了该示例的代码并再次查看了解您的查询但我可以看到:该行的两侧:“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”方法中的代码与网页中显示的代码不同:     public ActionResult Details(int id)

    此外,您可以将Person类作为Model类,其具有与Person内部相关的业务逻辑。 PersonRepository会有像(GetAll,GetByID)这样的方法。如果您有许多存储库,您也可以创建一个GenericRepository,如下所示:

    class GenericRepository<TEntity> where TEntity : class
    

    我希望现在好了。其他问题非常受欢迎。