简体   繁体   English

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

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

Update 3/31/2017 更新3/31/2017

I've learned a few more things since this post, so want to give one important reason to use ToList when returning from the repository - calling ToList will (when using IQueryable) execute the translated SQL on the database instead of pulling records into memory and then filtering. 自从这篇文章以来我已经学到了更多的东西,所以想要从存储库返回时使用ToList一个重要原因 - 调用ToList将(当使用IQueryable时)在数据库上执行已翻译的SQL而不是将记录拉入内存和然后过滤。 I don't believe the implicit cast to IEnumerable or IList does this. 我不相信IEnumerable或IList的隐式转换会这样做。


Following some of the tutorials on the MSDN website, I have utilized the generic repository layer in my application. 在MSDN网站上的一些教程之后,我在我的应用程序中使用了通用存储库层。 This repository layer is called by my service layer, which is in turn called by the controller. 此存储库层由我的服务层调用,而服务层又由控制器调用。

Looking at the generic repository, the data is fetched and is returned by calling ToList() . 查看通用存储库,获取数据并通过调用ToList()返回。 However, the return type of the method is IEnumerable which means the service layer must accept IEnumerable and before returning to the controller it must once again call a ToList() on the IEnumerable . 但是,该方法的返回类型是IEnumerable ,这意味着服务层必须接受IEnumerable并且在返回控制器之前,它必须再次调用IEnumerable上的ToList()

Example - Repository: 示例 - 存储库:

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

Example - Service Layer 示例 - 服务层

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

From the reading that I've done, it seems to be best to simply present to the controller a List of objects that it needs versus an IEnumerable or IQueryable . 从我已经完成的阅读中,似乎最好只向控制器提供它需要的对象List ,而不是IEnumerableIQueryable

Therefore, I think it would be better to instead of returning an IEnumerable to return an IList instead. 因此,我认为最好不要返回IEnumerable来返回IList Am I missing something here - why did the MSDN team choose IEnumerable for the design and call ToList ? 我在这里遗漏了什么 - 为什么MSDN团队选择IEnumerable进行设计并调用ToList Where would this be useful?? 这会有用吗? In my eyes it seems to be inefficient and pointless to do that conversion more than once, especially if dealing with a large set of data. 在我看来,不止一次进行转换似乎是低效且毫无意义的,特别是在处理大量数据时。

I apologize in advance if this is not clear or there is already an answer, but I have been searching and reading the other posts IEnumerable vs IQueryable vs IList, but I still do not understand this particular issue. 如果不清楚或已经有答案,我提前道歉,但我一直在寻找和阅读其他帖子IEnumerable vs IQueryable vs IList,但我仍然不明白这个特殊问题。

Return minimal interface that works for your particular case . 返回适合您特定情况的最小接口。

Often IEnumerable<T> is enough and give more flexibility, but if you see yourself need to use .ToList() often (and for valid reasons) return IList<T> or even List<T> . 通常IEnumerable<T>足够并且提供更大的灵活性,但是如果你发现自己需要经常使用.ToList() (并且出于正当理由)返回IList<T>甚至List<T>

Notes 笔记

  • IEnumerable<T> allows much easier lazy evaluation and unit testing (since it is smaller than IList - so try to stick with it. IEnumerable<T>允许更容易的懒惰评估和单元测试(因为它比IList小 - 所以试着坚持下去。
  • your sample does not show valid reasons to call .ToList() - combining IEnumerable<T> till you know what exactly you are looking for may even get you better performance (ie if after several checks you decide you need just one element but ToList will force you to fetch 10000). 你的样本没有显示有效的理由来调用.ToList() - 结合IEnumerable<T>直到你知道你究竟在寻找什么甚至可以让你获得更好的表现(即如果经过多次检查你决定只需要一个元素但ToList会强迫你获取10000)。

You're fine. 你没事。 The main thing that is happening right now is that the .ToList() in the repo is actually executing the query against the database. 现在正在发生的主要事情是repo中的.ToList()实际上正在对数据库执行查询。 But returning that list as IEnumerable, all you're really doing is boxing it so that the result is generic and unalterable. 但是将该列表作为IEnumerable返回,你所做的只是将它装箱,以便结果是通用且不可更改的。 There's some overhead there to unbox later on but since the duty of the repository is to return the REQUESTED data, you should return it like this imo. 稍后在unbox上有一些开销,但由于存储库的职责是返回REQUESTED数据,你应该像这样的imo返回它。

I think this is probably what the team was thinking. 我认为这可能是团队的想法。 You asked for this data, so here it is. 你问过这个数据,所以就在这里。 If you need to do further editing on it, you'll have to enumerate it again in order to make any modifications to that list. 如果您需要对其进行进一步编辑,则必须再次枚举它才能对该列表进行任何修改。 There's nothing wrong with that. 这没什么不对。 In fact, it supports SoC. 实际上,它支持SoC。

Typically, my repos return IEnumerable, then if my service layer needs to return something like a dto or viewmodel, I'll use that IEnum to build the new object: 通常,我的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.

相关问题 C#使用.ToList()将IEnumerable转换为IList? - C# Convert IEnumerable to IList using .ToList()? 使用IEnumerable和ICollection与IList的自定义集合 - Custom Collection using IEnumerable vs ICollection vs IList 使用IList和IEnumerable的通用逆变量 - Using generic contravariant with IList and IEnumerable 使用ToList()与新列表(IEnumerable)之间的性能差异 <T> ) - Performance Difference between using ToList() vs. new List(IEnumerable<T>) 在 IEnumerable 上使用 ToList() 方法<t>这已经是一个列表<t></t></t> - Using ToList() method on IEnumerable<T> which is already a List<T> IList 的百分比变化<t>返回 IList<t> 使用 LINQ</t></t> - Percent change of a IList<T> returning IList<T> using LINQ 使用 IList IEnumerable 存储库实现分页列表 - Implement Paged List with IList IEnumerable Repository 使用LINQ将IEnumerable转换为IList以使用不同的日期填充ListView适配器 - Converting IEnumerable to IList to populate ListView Adapter with Distinct Dates using LINQ 为什么使用数组而不是链接列表实现IEnumerable(或IList)? - Why is an IEnumerable(or IList) implemented using arrays instead of Linked Lists? IEnumerable vs ToList直接在视图中进行迭代 - IEnumerable vs ToList while directly iterating in view
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM