仓储模式 - 方法太多

11

我经常看到像这样的示例仓库模式:

public interface IRepository<T>
{
    T GetById(int id);
    IEnumerable<T> GetAllByName(string name);
}

但是,当您需要进行复杂搜索时,该如何处理呢?我认为向接口添加许多方法并使其看起来像这样并不是一个好主意:

IEnumerable<T> GetAllByFirstName(string name);
IEnumerable<T> GetAllByLastName(string name);
IEnumerable<T> GetAllByFirstAndLastName(string name);
IEnumerable<T> GetAllByAddress(string name);
...
...
...
6个回答

8
使用谓词构建器动态构建where条件。
public interface IRepository<T>
{
    T GetById(int id);

    IEnumerable<T> GetAllBy(Expression<Func<T, bool>> predicate);
}

然后构建条件。
  var predicate = PredicateBuilder.True<Customer>();
  if (!string.IsNullOrEmpty(FirstName))
  {
       predicate = predicate.And(d => d.FirstName.Contains(FirstName));
  }

  if (!string.IsNullOrEmpty(LastName))
  {
       predicate = predicate.And(d => d.LastName.Contains(LastName));
  }

  var products = productRepo.GetAllBy(predicate);

创建一个类来传递搜索条件。
public class CustomerFilterCriteria
{
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string Address { get; set; }

}

public interface IRepository<T>
{
    T GetById(int id);
    IEnumerable<T> GetAllBy(CustomerFilterCriteria criteria);
}

2
如果我不能使用表达式怎么办?例如,如果我必须在存储过程中使用仓储后面呢? - Books
自从这个回答发布以来,LINQ 是否已经集成了这些功能? - Isaac Kleinman

2
问题:如果您将公开特定类型的方法(或者所有实体都具有FirstName、LastName、Address等),为什么要使存储库通用?
如果您的底层数据资源支持LINQ表达式树,则常见签名也将是通用的,例如。
IEnumerable<TEntity> Query(Expression<Func<TEntity, Boolean>> filter)

如果您希望查询可以“堆叠”,您可以公开一个IQueryable。

IQueryable<TEntity> Query(Expression<Func<TEntity, Boolean>> filter)

1
您可以添加一个过滤器模型并检查哪些过滤器已经被填充,如下所示:
IEnumerable<T> GetAllByFiilter(FilterModel filter);


public class FilterModel {
   public string Lastname {get;set;}
   public string Firstname {get;set;}
}


public IEnumerable<T> GetAllByFilter(FilterModel filter) {
   if(!string.IsNullOrWhiteSpace(filter.Lastname) { 
     //add restriction
   }
   // .. etc ..
}

1
这是我在仓储模式上提供的方法:
 public interface IRepository<T> : IDisposable
    {
        void Create(T entity);

        void Delete(T entity);

        void Update(T entity);

        IQueryable<T> GetAll();

        T GetBy(Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] includes);
    }

我个人认为最好允许稍后查询,因为有时候你需要它,我也喜欢拥有一个通用的getby方法。这个组合使得所有我的类型化存储库都以通用方式提供,没有单独的实体配置。

在这里阅读我的文章http://blog.staticvoid.co.nz/2011/10/staticvoid-repository-pattern-nuget.html


0
“get 方法” 可以是独立的接口:
    public interface IGetMethod<T>
    {
       IEnumerable<T> get(String name);
    }

    class GetByName<T> : IGetMethod<T>
    {
       IEnumerable<T> get(String name)
       {
           // ...
       }
    }

    public interface IRepository<T>
    {

        IEnumerable<T> GetAllByMethod(IGetMethod<T> method, string name);
    }

0

有一个通用仓储

public interface IRepository<T>
{
    T GetById(int id);
    IEnumerable<T> GetAllBy(Expression<Func<T, bool>> predicate);
}

然后有更具体的存储库

public interface IUserRepository : IRepository<T>
    {
        User GetByName(string name);
    }

这样你的通用存储库就可以处理所有的CRUD操作,而你的实际存储库则可以处理其他任何事情


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接