我们有一条规则,不得将IQueryable<T>
或IEnumerable<T>
暴露在服务层之外,这样下游代码就无法修改去往数据库的查询。这意味着我们返回的类型类似于IList或ICollection。
[我想知道如何编写一次linq查询以在不将子集合定义为IQueryable
或IEnumerable
的情况下单次访问数据库来获取父代及其子代。
例如,假设从服务返回的类型是ICollection<Parent>
,其中Parent
定义为:
public class Parent { public int ParentId { get; set; } public string ParentName { get; set; } public ICollection<Child> Children { get; set; } }
如果我将查询定义为此...
from p in dbContext.Parents where p.Name.Contains("test") select new Parent { Children =from c in dbContext.Children where c.ParentId == p.ParentId select c; }
由于
IQueryable
未实现ICollection
,因此无法编译。如果我将.ToList()
添加到父项和子项集合中,它将进行编译,但是现在它将为每个父项进行一次单独的数据库访问以获取其子项。
当我写这个问题时,我想到答案可能是编写Linq查询以选择匿名类型,然后将其映射到实际类型以返回。我们使用可以协助映射的AutoMapper。有什么原因不起作用?在映射对象之前,是否必须调用.ToList()
以确保映射时不会遇到相同的问题?
我们有一条规则,不得在服务层之外公开IQueryable
如果您在Parent
实体中具有如下导航属性:
public class Parent
{
public int ParentId { get; set; }
public string ParentName { get; set; }
public virtual ICollection<Child> Children { get; set; }
//..
}
您可以在内部使用Anon查询,使用普通ol'EF且不使用AutoMapper来执行此操作,但仍会得到最终结果中返回的强类型对象:
Select