1

我是 ASP.NET MVC 新手(但 .NET 经验丰富的开发人员),我正在尝试学习如何正确设置 Web 应用程序基础结构。存储库模式是我这些天正在处理的,在过去几天阅读了数十篇博客/文章/答案之后,我仍然不确定如何正确使用它。我正在向Pro ASP.NET MVC 4 Adam Freeman学习,这里是基于本书的存储库接口代码:

public interface IRepository<T>
{
    IQueryable<T> FindAll();
    IQueryable<T> Find(Expression<Func<T, bool>> predicate);

    void Add(T newEntity);
    void Remove(T entity);

    T FindById(long id);
}

在网上进行更多研究后,我意识到很多人认为从存储库返回 IQueryable 是不好的做法,我可以(大部分)理解原因。但是,我似乎无法找到关于替代方案的答案?我知道为每个实体拥有一个自定义存储库的想法,该存储库对每个可能的查询都有专门的方法,基本上会返回 IEnumerable 而不是 IQueryable ......但这对我来说似乎不合适(这也不是优雅的解决方案许多代码编写和可能的代码冗余等......)。

还有什么其他选择?

4

2 回答 2

7

你有两个选择。

规格图案

第一个是使用规范模式。您创建一组用于限制搜索结果的类。

维基百科的文章有点差,因为它没有展示如何编写业务规范(即“真实”规范)。但是您基本上在业务规范中使用较低级别的规范(和/或等)。

通过这样做,您可以拥有更简单的存储库类,而不是对这些规范进行编码。

特定的存储库。

为每个根聚合(订单、用户等)创建一个存储库。每个存储库都有适用于特定业务需求的独特查询方法。

用户存储库可能有例如

IPagedResult<User> FindDisabledUser(int pageNumber, int pageSize);

订单库可能有

IPagedResult<User> GetOrdersReadyForShipping(DateTime orderAfterThisDate);

我写了一组数据层文章:http: //blog.gauffin.org/tag/data-access/。其中之一还解释了为什么在存储库中公开不是一个好主意IQueryable<T>

于 2013-05-31T09:40:03.407 回答
4

根据我在原始问题下的评论,这就是我将如何实现需要更复杂查询要求的存储库。我还为实体框架包含了我的 DbContext 对象。

我喜欢这种模式,因为它将实体框架实现隐藏在存储库后面,确保实体框架不会与您的应用程序紧密耦合。

public class PersonRepository: IPersonRepository
{
    public List<Person> ReadAll()
    {
        using (var context = new EfContext())
            return context.Persons.ToList();
    }

    public List<Person> ReadPage(int pageIndex, int itemCount)
    {
        using (var context = new EfContext())
            return context.Persons
                          .Skip(pageIndex * itemCount)
                          .Take(itemCount)
                          .ToList();

    }

    public List<Person> ReadAllWhoseNamesStartWith(string nameExpression)
    {
        using (var context = new EfContext())
            return context.Persons
                          .Where(r => r.Name.StartsWith(nameExpression)
                          .ToList();
    }

    public List<Person> ReadAllWhoseFavouriteColorIs(string color)
    {
        using (var context = new EfContext())
            return context.Persons
                          .Where(r => r.FavoriteColor.StartsWith(color)
                          .ToList();
    }
}

public class EfContext: DbContext
{
    public EfContext(): base("DefaultConnection")
    {
    }

    public DbSet<Person> Persons { get; set; }
    public DbSet<Car> Cars { get; set; }
    public DbSet<Car> Houses { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Database.SetInitializer<EfContext>(null);
        base.OnModelCreating(modelBuilder);
    }
}
于 2013-05-31T02:24:35.560 回答