开发者

Repository Pattern w/EF 4 - Am I on the right track?

开发者 https://www.devze.com 2023-02-16 06:43 出处:网络
So I have been beating my head into the wall for the last few weeks trying to get this whole pattern of Service/Repository/UnitOfWork, and I have come to the following conclusions and wanted to see if

So I have been beating my head into the wall for the last few weeks trying to get this whole pattern of Service/Repository/UnitOfWork, and I have come to the following conclusions and wanted to see if any experts thought I was on the right track.

I am using Ninject to inject these interfaces into the constructors of each layer.

I am using a RepositoryBase(Of TEntity) that all my specific repositories will derive from and implement their own interface:

Interfaces

Public Interface IUnitOfWork
    Inherits IDisposable

    Sub Commit()

End Interface

Public Interface IRepository(Of TEntity As Class)
    Function Query(Predicate As Expressions.Expression(Of Func(Of TEntity, Boolean))) As IQueryable(Of TEntity)
    Function GetAll() As IEnumerable(Of TEntity)
    Function GetFirst(Predicate As Expressions.Expression(Of Func(Of TEntity, Boolean))) As TEntity
    Function GetSingle(Predicate As Expressions.Expression(Of Func(Of TEntity, Boolean))) As TEntity
    Sub Add(Entity As TEntity)
    Sub Attach(Entity As TEntity)
    Sub Delete(Entity As TEntity)
    Sub Save(Entity As TEntity)

End Interface

Public Interface ICategoryRepository
    Function GetCategories() As IEnumerable(Of Category)
    Function GetCategoryByID(ID As Integer) As Category
    Sub SaveCategory(Category As Category)

End Interface

Repository/UnitOfWork Implementations

Public MustInherit Class RepositoryBase(Of TEntity As Class)
    Implements IRepository(Of TEntity)

    Protected Context As GTGContext
    Protected ObjectSet As ObjectSet(Of TEntity)

    Public Sub New(UnitOfWork As IUnitOfWork)
        Context = CType(UnitOfWork, UnitOfWork).Context
        ObjectSet = Context.CreateObjectSet(Of TEntity)()

    End Sub

    Protected Sub Add(Entity As TEntity) Implements Core.Interfaces.IRepository(Of TEntity).Add
        ObjectSet.AddObject(Entity)
    End Sub

    Protected Sub Attach(Entity As TEntity) Implements Core.Interfaces.IRepository(Of TEntity).Attach
        ObjectSet.Attach(Entity)
    End Sub

    Protected Sub Delete(Entity As TEntity) Implements Core.Interfaces.IRepository(Of TEntity).Delete
        ObjectSet.DeleteObject(Entity)
    End Sub

    Protected Function GetAll() As System.Collections.Generic.IEnumerable(Of TEntity) Implements Core.Interfaces.IRepository(Of TEntity).GetAll
        Return ObjectSet.AsEnumerable
    End Function

    Protected Function GetFirst(Predicate As System.Linq.Expressions.Expression(Of System.Func(Of TEntity, Boolean))) As TEntity Implements Core.Interfaces.IRepository(Of TEntity).GetFirst
        Return ObjectSet.Firs开发者_C百科t(Predicate)
    End Function

    Protected Function GetSingle(Predicate As System.Linq.Expressions.Expression(Of System.Func(Of TEntity, Boolean))) As TEntity Implements Core.Interfaces.IRepository(Of TEntity).GetSingle
        Return ObjectSet.Single(Predicate)
    End Function

    Protected Function Query(Predicate As System.Linq.Expressions.Expression(Of System.Func(Of TEntity, Boolean))) As System.Linq.IQueryable(Of TEntity) Implements Core.Interfaces.IRepository(Of TEntity).Query
        Return ObjectSet.Where(Predicate)
    End Function

    Protected Sub Save(Entity As TEntity) Implements Core.Interfaces.IRepository(Of TEntity).Save

    End Sub

End Class

Public Class CategoryRepository
    Inherits RepositoryBase(Of Category)
    Implements ICategoryRepository

    Public Sub New(UnitOfWork As IUnitOfWork)
        MyBase.New(UnitOfWork)

    End Sub

    Public Function GetCategories() As System.Collections.Generic.IEnumerable(Of Core.Entities.Category) Implements Core.Interfaces.ICategoryRepository.GetCategories
        'Return GetAll()
        Return Context.Categories.Include("SubCategories").AsEnumerable

    End Function

    Public Function GetCategoryByID(ID As Integer) As Core.Entities.Category Implements Core.Interfaces.ICategoryRepository.GetCategoryByID
        Return GetSingle(Function(x) x.ID = ID)

    End Function

    Public Sub SaveCategory(Category As Core.Entities.Category) Implements Core.Interfaces.ICategoryRepository.SaveCategory
        ObjectSet.First(Function(x) x.ID = Category.ID)
        ObjectSet.ApplyCurrentValues(Category)

    End Sub

End Class

Public Class UnitOfWork
    Implements IUnitOfWork

    Public Property Context As GTGContext

    Public Sub New()
        _Context = New GTGContext

    End Sub

    Public Sub Commit() Implements Core.Interfaces.IUnitOfWork.Commit
        _Context.SaveChanges()

    End Sub

#Region "IDisposable Support"

    Private _IsDisposed As Boolean

    Protected Overridable Sub Dispose(Disposing As Boolean)
        If (Not _IsDisposed) Then
            If (Disposing) Then
                If (_Context IsNot Nothing) Then
                    _Context.Dispose()
                End If
            End If
        End If

        _IsDisposed = True

    End Sub

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

#End Region

End Class

Service Implementations

Public MustInherit Class ServiceBase(Of TEntity As Class)
    Implements IService(Of TEntity)

End Class

Public Class CategoryService
    Inherits ServiceBase(Of Category)
    Implements ICategoryService

    Private Repository As ICategoryRepository

    Public Sub New(Repository As ICategoryRepository)
        Me.Repository = Repository

    End Sub

    Public Function GetCategories() As System.Collections.Generic.IEnumerable(Of Core.Entities.Category) Implements Core.Interfaces.ICategoryService.GetCategories
        Return Repository.GetCategories

    End Function

    Public Function GetCategoryByID(ID As Integer) As Core.Entities.Category Implements Core.Interfaces.ICategoryService.GetCategoryByID
        Return Repository.GetCategoryByID(ID)

    End Function

    Public Sub SaveCategory(Category As Core.Entities.Category) Implements Core.Interfaces.ICategoryService.SaveCategory
        Repository.SaveCategory(Category)

    End Sub

End Class

Any flaws that you see here? Suggestions? MAGIC? :)


Seems like i'm answering a question for you everyday on the same topic. :)

Anyway - onto the question - i agree with @qes.

The point of the Service/Repository marriage is so your Repositories are simple, and it's up to the Service to provide the logic to execute the queries. Your service should have specific methods required for the "consumer" (the MVC app), such as:

public ICollection<Order> FindOrdersForCustomer(int customerId)
{
   return _orderRepository
      .Query()
      .Where(order => order.CustomerId == customerId)
      .ToList();
}

Simply wrapping calls is pointless. Your Service should act as a facade between your MVC app and your underlying Repository.

Basically, your OrderRepository (for example), defines operations on Orders. Your OrderService should then provide all the different possible ways an Order can be added/retrieved/saved/deleted.

Which is why i'm not a fan of the "Single", "First", "All" methods on the Repository.

I only have one "Read" method, called "Find".

The service should then have the "Single", "First", "All" methods, simply using basic LINQ to materialize upon the Find method.

Your Repository is overly complicated IMO.

My Repository interface only has 3 methods:

IQueryable<T> Find()
void Save(T entity)
void Delete(T entity)

And my Service interface has anywhere between 5 and 20.


What is the point of the Service class if it's only code is passing through to the Repository?

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号