使用tolist()与使用iList从存储库返回iEnumerable



更新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,但我仍然不明白这个特定的问题。

<</p>

返回最小接口,可用于您的特定情况。

通常IEnumerable<T>就足够了,并且具有更大的灵活性,但是如果您发现自己需要经常使用.ToList()(并且出于正当原因)返回IList<T>甚至List<T>

笔记

  • IEnumerable<T>允许更轻松的懒惰评估和单元测试(因为它小于IList-因此请坚持使用。
  • 您的示例没有显示致电.ToList()的正当理由 - 结合IEnumerable<T>,直到您知道到底要寻找的是什么,甚至可以使您的性能变得更好(即,在几次检查后,您决定只需要一个元素,但是ToList会强迫您去提取10000)。

你很好。目前正在发生的主要事情是,存储库中的.tolist()实际上是针对数据库执行查询。但是,将该列表归还为IEnumerable,您真正要做的就是拳击它,以使结果是通用和不可改变的。稍后,那里有一些开销要拆开,但是由于存储库的职责是返回请求的数据,因此您应该像IMO一样将其返回。

我认为这可能是团队在想的。您索要此数据,所以就在这里。如果您需要对其进行进一步的编辑,则必须再次列举它,以便对该列表进行任何修改。这没什么错。实际上,它支持Soc。

通常,我的存储库返回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;

最新更新