关于Repository模式的学习

  定义(来自Martin Fowler的《企业应用架构模式》):

  Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.

  个人理解:Repository是一个独立的层,介于领域层与数据映射层(数据访问层)之间。它的存在让领域层感觉不到数据访问层的存在,它提供一个类似集合的接口提供给领域层进行领域对象的访问。Repository是仓库管理员,领域层需要什么东西只需告诉仓库管理员,由仓库管理员把东西拿给它,并不需要知道东西实际放在哪。

  tabbycat的理解(来源):

  • Repository模式是架构模式,在设计架构时,才有参考价值;
  • Repository模式主要是封装数据查询和存储逻辑;

  • Repository模式实际用途:更换、升级ORM引擎,不影响业务逻辑;

  • Repository模式能提高测试效率,单元测试时,用Mock对象代替实际的数据库存取,可以成倍地提高测试用例运行速度。

  评估:应用Repository模式所带来的好处,远高于实现这个模式所增加的代码。只要项目分层,都应当使用这个模式。

  关于泛型Repository接口(来源):

  • 仅使用泛型Repository接口并不太合适,因为Repository接口是提供给Domain层的操作契约,不同的entity对于Domain来说可能有不同的操作约束。因此Repository接口还是应该单独针对每个Eneity类来定义。
  • 泛型的Repository<T>类仍然用来减少重复代码,只是不能被UserRepository类直接继承,因为这样Delete方法将侵入User类,所以改为在UserRepository中 组合一个Repository<T>,将开放给domain可见且又能使用泛型重用的功能委托给这个Repository<T>

  Repository与Dal的区别(来源):

  • Repository是DDD中的概念,强调Repository是受Domain驱动的,Repository中定义的功能要体现Domain的意图和约束,而Dal更纯粹的就是提供数据访问的功能,并不严格受限于Business层。
  • 使用Repository,隐含着一种意图倾向,就是 Domain需要什么我才提供什么,不该提供的功能就不要提供,一切都是以Domain的需求为核心;而使用Dal,其意图倾向在于我Dal层能使用的数 据库访问操作提供给Business层,你Business要用哪个自己选。换一个Business也可以用我这个Dal,一切是以我Dal能提供什么操 作为核心。

  使用该模式的最大好处就是将领域模型从客户代码和数据映射层之间解耦出来。

  其实我们可以把它理解为DAL层,但又与DAL层有一定的区别,Repository是DDD中的概念,强调Repository是受Domain驱动的,Repository中定义的功能要体现Domain的意图和约束,而DAL层更纯粹的就是提供数据访问的功能,并不严格受限于Business层。

  使用Repository,隐含着一种意图倾向,就是 Domain需要什么我才提供什么,不该提供的功能就不要提供,一切都是以Domain的需求为核心;而使用DAL,其意图倾向在于我DAL层能使用的数据库访问操作提供给Business层,你Business要用哪个自己选。换一个Business也可以用我这个DAL,一切是以我DAL能提供什么操作为核心

  这里再简单说说Core里的Service文件,它相对Repository是处理一些复杂一点的业务逻辑,而Repository所提供的功能是相对比较单一的,比如添加用户,Repository就是操作数据库保存操作,而Service则会先进行一系列的逻辑判断,是否存在该用户的,再调用Repository里的保存用户操作。

  我们来看下在LinqToSql中如何应用该模式。

1. 我们将对实体的公共操作部分,提取为IRepository接口,比如常见的增加,删除等方法。如下代码:

interface IRepository<T> where T : class
{
  IEnumerable<T> FindAll(Func<T, bool> exp);

  void Add(T entity);

  void Delete(T entity);

  void Save(); 
}

2.下面我们实现一个泛型的类来具体实现上面的接口的方法。

public class Repository<T> : IRepository<T> where T : class

{

  public DataContext context;

  public Repository(DataContext context)

  { 
    this.context = context; 
  } 


  public IEnumerable<T> FindAll(Func<T, bool> exp)
  {
    return context.GetTable<T>().Where(exp); 
  } 

  public void Add(T entity)
   {
    context.GetTable<T>().InsertOnSubmit(entity);
  } 


  public void Delete(T entity)
  {
    context.GetTable<T>().DeleteOnSubmit(entity); 
  } 


  public void Save()
  { 
    context.SubmitChanges();
  }

}

3.上面我们实现是每个实体公共的操作,但是实际中每个实体都有符合自己业务的逻辑。我们单独定义另外一个接口,例如:

interface IBookRepository : IRepository<Book>
{
  IList<Book> GetAllByBookId(int id);
}

4.最后该实体的Repository类实现如下:

public class BookRepository : Repository<Book>, IBookRepository 
{ 

  public BookRepository(DataContext dc)        : base(dc)
  {
  }

  public IList<Book> GetAllByBookId(int id)
      {

    var listbook = from c in context.GetTable<Book>()

           where c.BookId == id 

           select c;

    return listbook.ToList();
  }

} 

上面只是为大家提供了一个最基本使用框架。

原文地址:

http://www.cnblogs.com/carysun/archive/2009/03/20/repository.html

http://xdwangiflytek.iteye.com/blog/1395698

http://www.cnblogs.com/dudu/archive/2011/05/25/repository_pattern.html

✏️ 有任何想法?欢迎发邮件告诉老夫:daozhihun@outlook.com