Respository模式在示例中的实际目的小结一下
Repository是DDD中的概念,强调Repository是受Domain驱动的,Repository中定义的功能要体现Domain的意图和约束,而Dal更纯粹的就是提 供数据访问的功能,并不严格受限于Business层。
使用Repository,隐含着一种意图倾向,就是 Domain需要什么我才提供什么,不该提供的功能就不要提供,一切都是以Domain的需求为核心;而使用Dal,其意图倾向在于我Dal层能使用的数 据库访问操作提供给Business层,你Business要用哪个自己选。换一个Business也可以用我这个Dal,一切是以我Dal能提供什么操 作为核心。
在LCL中,一个存储库类实现了IRepository<TEntity,TPrimaryKey> 您需要手工注入 IRepository<TEntity> (IRepository<TEntity, TPrimaryKey>)。 一个示例应用程序服务使用一个存储库来将一个实体插入到数据库:
public class RoleAppService : IRoleAppService { private readonly IRepository<Role> _roleRepository; public RoleAppService(IRepository<Role> roleRepository) { _roleRepository = roleRepository; } public void CreateRole(Role input) { _roleRepository.Insert(input); } }
RoleAppService 注入IRepository<Role> ,并使用插入方法。
当您需要为该实体创建一个自定义存储库方法时,您只需要为实体创建一个存储库类。
一个Role实体的存储库定义如下所示:
public interface IRoleRepository : IRepository<Role> { }
IRoleRepository延伸 IRepository<TEntity>。它用于定义具有主键类型的Guid类型的实体。 如果您的实体的主键不是Guid,您可以扩展IRepository<TEntity,TPrimaryKey>:接口如下所示:
public interface IRoleRepository : IRepository<Role, long>
{
}
Role是实体类,请查看实体类的编写。
LCL的设计目的是独立于特定的ORM(对象/关系映射)框架或其他访问数据库的技术。存储库是在NHibernate,MongoDB和EntityFramework中实现的,它是开箱即用的。查看文档以实现在LCL中的存储库。
public interface IRepository<TAggregateRoot> where TAggregateRoot : class, IAggregateRoot { IRepositoryContext Context { get; } void Add(TAggregateRoot aggregateRoot); TAggregateRoot GetByKey(object key); IQueryable<TAggregateRoot> FindAll(); IQueryable<TAggregateRoot> FindAll(Expression<func<TAggregateRoot, dynamic=dynamic >> sortPredicate, SortOrder sortOrder); PagedResult<TAggregateRoot> FindAll(Expression<func<TAggregateRoot, dynamic=dynamic >> sortPredicate, SortOrder sortOrder, int pageNumber, int pageSize); IQueryable<TAggregateRoot> FindAll(ISpecification<TAggregateRoot> specification); IQueryable<TAggregateRoot> FindAll(ISpecification<TAggregateRoot> specification, Expression<func<TAggregateRoot, dynamic=dynamic >> sortPredicate, SortOrder sortOrder); PagedResult<TAggregateRoot> FindAll(ISpecification<TAggregateRoot> specification, Expression<func<TAggregateRoot, dynamic=dynamic >> sortPredicate, SortOrder sortOrder, int pageNumber, int pageSize); IQueryable<TAggregateRoot> FindAll(params Expression<func<TAggregateRoot, dynamic=dynamic >>[] eagerLoadingProperties); IQueryable<TAggregateRoot> FindAll(Expression<func<TAggregateRoot, dynamic=dynamic >> sortPredicate, SortOrder sortOrder, params Expression<func<TAggregateRoot, dynamic=dynamic >>[] eagerLoadingProperties); PagedResult<TAggregateRoot> FindAll(Expression<func<TAggregateRoot, dynamic=dynamic >> sortPredicate, SortOrder sortOrder, int pageNumber, int pageSize, params Expression<func<TAggregateRoot, dynamic=dynamic >>[] eagerLoadingProperties); IQueryable<TAggregateRoot> FindAll(ISpecification<TAggregateRoot> specification, params Expression<func<TAggregateRoot, dynamic=dynamic >>[] eagerLoadingProperties); IQueryable<TAggregateRoot> FindAll(ISpecification<TAggregateRoot> specification, Expression<func<TAggregateRoot, dynamic=dynamic >> sortPredicate, SortOrder sortOrder, params Expression<func<TAggregateRoot, dynamic=dynamic >>[] eagerLoadingProperties); PagedResult<TAggregateRoot> FindAll(ISpecification<TAggregateRoot> specification, Expression<func<TAggregateRoot, dynamic=dynamic >> sortPredicate, SortOrder sortOrder, int pageNumber, int pageSize, params Expression<func<TAggregateRoot, dynamic=dynamic >>[] eagerLoadingProperties); TAggregateRoot Find(ISpecification<TAggregateRoot> specification); TAggregateRoot Find(ISpecification<TAggregateRoot> specification, params Expression<func<TAggregateRoot, dynamic=dynamic >>[] eagerLoadingProperties); bool Exists(ISpecification<TAggregateRoot> specification); void Remove(TAggregateRoot aggregateRoot); void Update(TAggregateRoot aggregateRoot); }
Get方法用于获得给定主键(Id)的实体。如果数据库中没有给定Id的实体,它会抛出异常。单个方法与Get相似,但使用表达式而不是Id。因此,您可以编写一个lambda表达式来获得一个实体。示例用法:
var role = _roleRepository.GetByKey(42); var role = _roleRepository.Find(p => p.Name == "John");
注意,如果没有给定条件的实体,或者存在多个实体,那么单一方法会抛出异常。
FirstOrDefault是类似的,但是如果没有给定的Id或表达式的实体,则返回null(而不是抛出异常)。如果给定条件下有多个实体,则返回第一个实体。
FindAll返回这个IQueryable < T >。所以,你可以在它之后添加Linq的方法。例子:
//Example 1 var query = from role in _roleRepository.FindAll() where role.IsActive orderby role.Name select role; var role = query.ToList(); //Example 2: List<Role> roleList2 = _personRepository.FindAll().Where(p => p.Name.Contains("H")).OrderBy(p => p.Name).Skip(40).Take(20).ToList();
使用FindAll,几乎所有的查询都可以在Linq写。甚至可以在连接表达式中使用它。
当您从存储库方法中调用FindAll()时,必须有一个开放的数据库连接。这是因为IQueryable的延迟执行。 它不执行数据库查询,除非您调用ToList()方法,或者在foreach循环中使用IQueryable(或以某种方式访问查询的项)。 因此,当您调用ToList()方法时,数据库连接必须是活着的。 对于一个web应用程序,在大多数情况下,您并不关心这一点,因为MVC控制器方法是默认的工作单元, 并且数据库连接可以用于整个请求。请参阅UnitOfWork文档以更好地理解它。