存储库模式 - 方法太多

时间:2012-02-14 08:16:10

标签: c# design-patterns

我经常看到示例存储库模式,如下所示:

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 个答案:

答案 0 :(得分:6)

使用Predicate Builder动态构建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);
}

答案 1 :(得分:2)

问题:如果您要公开特定于类型的方法(或者您的所有实体是否具有FirstName,LastName,Address等?),为什么要使存储库具有通用性?

如果您的基础数据资源启用了LINQ表达式树,则公共签名也是通用的,例如

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

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

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

答案 2 :(得分: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

答案 3 :(得分:0)

您可以添加一个filtermodel并检查已填充的过滤器如下:

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 ..
}

答案 4 :(得分:0)

“get method”可以是它自己的接口:

    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);
    }

答案 5 :(得分: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内容和你的实际存储库