繁体   English   中英

使用ToList()和使用IList从存储库返回IEnumerable

[英]Returning IEnumerable from Repository using ToList() vs using IList

更新3/31/2017

自从这篇文章以来我已经学到了更多的东西,所以想要从存储库返回时使用ToList一个重要原因 - 调用ToList将(当使用IQueryable时)在数据库上执行已翻译的SQL而不是将记录拉入内存和然后过滤。 我不相信IEnumerable或IList的隐式转换会这样做。


在MSDN网站上的一些教程之后,我在我的应用程序中使用了通用存储库层。 此存储库层由我的服务层调用,而服务层又由控制器调用。

查看通用存储库,获取数据并通过调用ToList()返回。 但是,该方法的返回类型是IEnumerable ,这意味着服务层必须接受IEnumerable并且在返回控制器之前,它必须再次调用IEnumerable上的ToList()

示例 - 存储库:

public IEnumerable<TEntity> Get(
    Expression<Func<TEntity, bool>> filter = null,
    Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
    string includeProperties = "")
{
    IQueryable<TEntity> query = dbSet;

    if (filter != null)
    {
        query = query.Where(filter);
    }

    foreach (var includeProperty in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
    {
        query = query.Include(includeProperty);
    }

    return orderBy != null ? orderBy(query).ToList() : query.ToList();
}

示例 - 服务层

public IList<DOC> SearchDocuments(string docInfo)
{
    // build the predicate and logic, etc

    // grab all the matching documents with the relationships
    IEnumerable<DOC> documents = _unitOfWork.DocumentRepository.Get(
        predicate,
        p => p.OrderBy(d => d.DocInfo),
        "DocRelationship, DocRelationship.OtherDocTable");

    return documents.ToList();
} 

从我已经完成的阅读中,似乎最好只向控制器提供它需要的对象List ,而不是IEnumerableIQueryable

因此,我认为最好不要返回IEnumerable来返回IList 我在这里遗漏了什么 - 为什么MSDN团队选择IEnumerable进行设计并调用ToList 这会有用吗? 在我看来,不止一次进行转换似乎是低效且毫无意义的,特别是在处理大量数据时。

如果不清楚或已经有答案,我提前道歉,但我一直在寻找和阅读其他帖子IEnumerable vs IQueryable vs IList,但我仍然不明白这个特殊问题。

返回适合您特定情况的最小接口。

通常IEnumerable<T>足够并且提供更大的灵活性,但是如果你发现自己需要经常使用.ToList() (并且出于正当理由)返回IList<T>甚至List<T>

笔记

  • IEnumerable<T>允许更容易的懒惰评估和单元测试(因为它比IList小 - 所以试着坚持下去。
  • 你的样本没有显示有效的理由来调用.ToList() - 结合IEnumerable<T>直到你知道你究竟在寻找什么甚至可以让你获得更好的表现(即如果经过多次检查你决定只需要一个元素但ToList会强迫你获取10000)。

你没事。 现在正在发生的主要事情是repo中的.ToList()实际上正在对数据库执行查询。 但是将该列表作为IEnumerable返回,你所做的只是将它装箱,以便结果是通用且不可更改的。 稍后在unbox上有一些开销,但由于存储库的职责是返回REQUESTED数据,你应该像这样的imo返回它。

我认为这可能是团队的想法。 你问过这个数据,所以就在这里。 如果您需要对其进行进一步编辑,则必须再次枚举它才能对该列表进行任何修改。 这没什么不对。 实际上,它支持SoC。

通常,我的repos返回IEnumerable,然后如果我的服务层需要返回类似dto或viewmodel的东西,我将使用该IEnum来构建新对象:

var myEnumerable = _uow.MyJunk.Get(j => j.Stuff.Where(a => a.OtherJunk == something);
var myDtos = myEnumerable.Select(obj => new DtoClass { Foo = obj.Foo, Bar = obj.Bar };
return myDtos;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM