2017年3月31日更新
自从这篇文章以来我已经学到了更多的东西,所以想要从存储库返回时给出一个使用ToList
的重要理由 - 调用ToList
将(当使用IQueryable时)执行翻译数据库上的SQL而不是将记录拉入内存然后过滤。我不相信对IEnumerable或IList的隐式转换会这样做。
在MSDN网站上的一些教程之后,我在我的应用程序中使用了通用存储库层。该存储库层由我的服务层调用,而服务层又由控制器调用。
查看通用存储库,获取数据并通过调用ToList()
返回。但是,该方法的返回类型为IEnumerable
,这意味着服务层必须接受IEnumerable
,在返回控制器之前,必须再次调用ToList()
在IEnumerable
。
示例 - 存储库:
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
对象,而不是IEnumerable
或IQueryable
。
因此,我认为最好不要返回IEnumerable
而是返回IList
。我在这里遗漏了什么 - 为什么MSDN团队选择IEnumerable
进行设计并致电ToList
?这会有用吗?在我看来,不止一次进行转换似乎是低效且毫无意义的,特别是在处理大量数据时。
如果不清楚或者已经有答案,我提前道歉,但我一直在寻找和阅读其他帖子IEnumerable vs IQueryable vs IList,但我仍然不明白这个特殊问题。
答案 0 :(得分:9)
返回适合您特定情况的的最小界面。
通常IEnumerable<T>
足够并且提供更大的灵活性,但如果您发现自己需要经常使用.ToList()
(并且出于正当理由)请返回IList<T>
甚至List<T>
。
注释
IEnumerable<T>
允许更容易的懒惰评估和单元测试(因为它小于IList
- 所以尽量坚持下去。.ToList()
- 合并IEnumerable<T>
直到您知道您正在寻找什么甚至可以让您获得更好的表现(即,如果经过多次检查后您决定只需要一个元素,但ToList
将强制您获取10000)。答案 1 :(得分:2)
我认为这可能是团队的想法。你问过这个数据,所以就在这里。如果您需要对其进行进一步编辑,则必须再次枚举它才能对该列表进行任何修改。这没什么不对。实际上,它支持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;