问题
There seems to be lots of examples on implementing Repository pattern for Linq to SQL. Most of them featuring IRepository and DI; Some have implemented Unit of Work and some not. I tried to read as most of the results returned by searches on SO and Google on Linq to SQL repository patterns. Nevertheless I've not come across a complete solution yet.
From my readings I've implemented a repository pattern as shown below:
I'm using DI to register interfaces on which the repositories are depended:
this.container.RegisterType<IConnectionStringFactory, ConnectionStringFactory>(new ContainerControlledLifetimeManager(),
new InjectionConstructor(connectionString));
this.container.RegisterType<IDataContextFactory, DataContextFactory>();
Implementation of Repository pattern:
public interface IPrivilegeRepository : IRepository<PrivilegesEntity>
{
IList<MenuModel> GetRootMenu();
IList<MenuModel> GetChildMenu(int parentId);
}
public class PrivilegeRepository : Repository<PrivilegesEntity>, IPrivilegeRepository
{
#region IPrivilegeRepository Members
public IList<MenuModel> GetRootMenu()
{
return FindAll(menu => menu.ParentId == null)
.OrderBy(menu => menu.SortOrder)
.Select(c => EntityMapper.Privileges.ToBusinessObject(c))
.ToList();
}
public IList<MenuModel> GetChildMenu(int parentId)
{
return FindAll(menu => menu.ParentId == parentId)
.OrderBy(menu => menu.SortOrder)
.Select(menu => EntityMapper.Privileges.ToBusinessObject(menu))
.ToList();
}
#endregion
public PrivilegeRepository(IDataContextFactory dataContextFactory)
: base(dataContextFactory)
{
}
}
IRepository generic interface:
public interface IRepository<T> where T : class
{
IEnumerable<T> All();
IEnumerable<T> FindAll(Expression<Func<T, bool>> exp);
T Single(Expression<Func<T, bool>> exp);
T First(Expression<Func<T, bool>> exp);
}
Repository class is implemented as below with implementations of IRepository (not shown) and is having a dependency on IDataContextFactory which DI is taking care of:
public class Repository<T> : IRepository<T> where T : class
{
public Repository(IDataContextFactory dataContextFactory)
{
this.dataContextFactory = dataContextFactory;
}
}
Repositories are consumed using IoC:
PrivilegeRepository repository = container.Resolve<PrivilegeRepository>();
I'm returning result of queries as a collection of Business Object in order to avoid dependency on Linq to SQL on application layers where I consume repository. The above scenario works fine with my WPF application which is using MVVM pattern. I have ViewModel aks Presenter classes which are not depended of classes generated by Linq-SQL.
How do I extend this pattern so that I can save data to the Database. I'd like to pass Business Objects back to the repository and get them saved. Is it possible? How can I implement Unit of Work in such a scenario.
回答1:
Here is an answer of mine to a similar question.
The basic idea is that generic repository interfaces don't work so well, but generic repository implementations work great. It uses LINQ to SQL as the example ORM and should provide some insight to your question.
Be sure to read through Paul's answer as well, especially the comments.
回答2:
Well this is a problem I've seen a lot of times. You want to have the decoupling of your business objects from your data storage strategy. As your doing a projection to your business objects you lose a lot of the nice features of having a repository (you could return IQueryable for example making use of deffered execution). The only way you can implement this is by giving your Repository a dependency towards an IMapper<BusinessObject>
for example. This way you can map your business object to the object your repository needs in order to store something but leaving the abstraction in place as your business objects remain persistence ignorant.
来源:https://stackoverflow.com/questions/1624229/repository-pattern-with-linq-to-sql-using-ioc-dependency-injection-unit-of-wor