You can use a generic repository pattern. And this can be extended with very specific domain queries. Your DI container can then create the specific repository you require and you can work against it for all dataclasses.
If any questions about the code feel free to ask.
Im' gonna give you my VB.net code, hope it is usefull:
This is the interface you'll be working to. Saving and retrieving your Classes (They Must inherit from IEntity)
Public Interface IRepository
Function GetEntity(Of T As {EntityObject, IEntity})(id As Integer) As T
Function GetAll(Of T As {EntityObject, IEntity})() As IEnumerable(Of T)
Sub Add(Of T As {EntityObject, IEntity})(entity As T)
Sub Remove(Of T As EntityObject)(entity As T)
Sub Attach(Of T As EntityObject)(entity As T)
Sub Update(Of T As {EntityObject, IEntity})(entity As T)
Function ExecuteQuery(Of T As {EntityObject, IEntity})(query As IQuery(Of T)) As IQueryResult(Of T)
Function ExecuteQuery(Of T As {EntityObject, IEntity}, TResult)(query As IQuery(Of T, TResult)) As IQueryResult(Of TResult)
End Interface
The interface you must implement in your data objects
You can also use other then int for your PK:
Public Interface IEntity
Property Id As Int32
End Interface
The IQuery object, implement this for a specific query on your data:
Public Interface IQuery(Of T As {EntityObject, IEntity})
Function Execute(ByVal objectSet As ObjectSet(Of T)) As IQueryResult(Of T)
End Interface
Public Interface IQuery(Of T As {EntityObject, IEntity}, TResult)
Function Execute(ByVal objectSet As ObjectSet(Of T)) As IQueryResult(Of TResult)
End Interface
The QueryResult you'll be working to, and it's extendable
Public Interface IQueryResult(Of T)
Function UniqueResult() As T
Function List() As IEnumerable(Of T)
End Interface
Public Class LinqResult(Of T)
Implements IQueryResult(Of T)
Private ReadOnly _query As IQueryable(Of T)
Public Sub New(query As IQueryable(Of T))
_query = query
End Sub
Protected Overridable Function ExpandQuery(query As IQueryable(Of T)) As IQueryable(Of T)
Return query
End Function
Public Function UniqueResult() As T Implements IQueryResult(Of T).UniqueResult
Dim result = ExpandQuery(_query).SingleOrDefault()
If result Is Nothing Then
Throw New EntityNotFoundException(Of T)()
End If
Return result
End Function
Public Function List() As IEnumerable(Of T) Implements IQueryResult(Of T).List
Return ExpandQuery(_query).ToList()
End Function
End Class
Your ObjectcontextRepository, the actual implementation of your IRepository
Public Class EntityObjectContextRepository
Implements IRepository
Private ReadOnly Property _context As ObjectContext
Get
Return UnitOfWork.Current
End Get
End Property
Public Sub Add(Of T As {EntityObject, IEntity})(entity As T) Implements IRepository.Add
_context.CreateObjectSet(Of T)().AddObject(entity)
End Sub
Public Sub Attach(Of T As EntityObject)(entity As T) Implements IRepository.Attach
_context.Attach(entity)
'_context.CreateObjectSet(Of T)().Attach(entity)
End Sub
Public Sub Update(Of T As {EntityObject, IEntity})(ByVal entity As T) Implements IRepository.Update
_context.CreateObjectSet(Of T)().Attach(entity)
_context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified)
End Sub
Public Function ExecuteQuery(Of T As {EntityObject, IEntity})(query As IQuery(Of T)) As IQueryResult(Of T) Implements IRepository.ExecuteQuery
Return query.Execute(_context.CreateObjectSet(Of T))
End Function
Public Function ExecuteQuery(Of T As {EntityObject, IEntity}, TResult)(ByVal query As IQuery(Of T, TResult)) As IQueryResult(Of TResult) Implements IRepository.ExecuteQuery
Return query.Execute(_context.CreateObjectSet(Of T))
End Function
Public Function GetAll(Of T As {EntityObject, IEntity})() As IEnumerable(Of T) Implements IRepository.GetAll
Return _context.CreateObjectSet(Of T).ToList().Where(Function(c) c.EntityState <> EntityState.Deleted)
End Function
Public Function GetEntity(Of T As {EntityObject, IEntity})(id As Integer) As T Implements IRepository.GetEntity
Dim entity = _context.CreateObjectSet(Of T)().SingleOrDefault(Function(x) x.Id = id)
Return ReturnEntityWhenItExists(entity)
End Function
Public Sub Remove(Of T As EntityObject)(entity As T) Implements IRepository.Remove
_context.DeleteObject(entity)
End Sub
Private Function ReturnEntityWhenItExists(Of T As {EntityObject, IEntity})(ByVal entity As T) As T
If entity IsNot Nothing AndAlso entity.EntityState <> EntityState.Deleted Then
Return entity
End If
Throw New EntityNotFoundException(Of T)()
End Function
End Class
The Unit of working wrapping this all:
Public Class UnitOfWork
Implements IDisposable
Private Shared _dataContext As ObjectContext
Public Shared ReadOnly Property Current As ObjectContext
Get
If _dataContext Is Nothing Then
Throw New UnitOfWorkException(ResourceRetriever.GetResource(Of String)("ExceptionUnitOfWorkNotInitializedMessage"))
End If
Return _dataContext
End Get
End Property
Public Sub New()
Me.New(New YourDataModelContainer())
End Sub
Public Sub New(ByVal objectContext As ObjectContext)
If _dataContext IsNot Nothing Then
Throw New UnitOfWorkException(ResourceRetriever.GetResource(Of String)("ExceptionUnitOfWorkAlreadyInitializedMessage"))
End If
_dataContext = objectContext
End Sub
Public Sub Complete()
If _dataContext Is Nothing Then
Throw New UnitOfWorkException(ResourceRetriever.GetResource(Of String)("ExceptionUnitOfWorkNotInitializedMessage"))
End If
_dataContext.SaveChanges()
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
If _dataContext IsNot Nothing Then
_dataContext.Dispose()
_dataContext = Nothing
End If
End Sub
End Class
An example of a query:
Public Class GetAllBuildingsQuery
Implements IQuery(Of DataAccess.Building, BuildingDto)
Public Function Execute(ByVal objectSet As ObjectSet(Of Building)) As IQueryResult(Of BuildingDto) Implements IQuery(Of Building, BuildingDto).Execute
Dim query = objectSet.Select(Function(g) New BuildingDto() With {.Description = g.Name, .Id = g.Id})
Return New LinqResult(Of BuildingDto)(query)
End Function
End Class
How it is implemented in the service call:
Public Class EmployeeService
Implements IEmployeeService
Private ReadOnly _repository As IRepository
Public Sub New(ByVal repository As IRepository)
_repository = repository
End Sub
Public Function GetAllEmployees() As IEnumerable(Of EmployeeOverviewDto) Implements IEmployeeService.GetAllEmployees
Dim employees = _repository.ExecuteQuery(EmployeeQueries.GetAllEmployeesForOverview()).List()
Return employees
End Function
End Class