ada*_*101 3 c# linq entity-framework automapper
我们有一个规则,即不公开服务层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; }
}
Run Code Online (Sandbox Code Playgroud)
如果我将查询定义为此...
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;
}
Run Code Online (Sandbox Code Playgroud)
它不会编译,因为IQueryable没有实现ICollection。如果我将其添加.ToList()到父级和子级集合中,它将进行编译,但是现在它将为每个父级进行一次单独的数据库访问以获取其子级。
当我写这个问题时,我想到可能的答案是编写Linq查询以选择匿名类型,然后将其映射到实际类型以返回。我们使用可以协助映射的AutoMapper。有什么原因不起作用?我是否必须.ToList()在映射对象之前调用以确保映射时不会遇到相同的问题?
如果您的Parent实体中具有如下导航属性:
public class Parent
{
public int ParentId { get; set; }
public string ParentName { get; set; }
public virtual ICollection<Child> Children { get; set; }
//..
}
Run Code Online (Sandbox Code Playgroud)
然后,我建议您在服务层中创建两个新类(可以是ParentViewModel和ChildViewModel)来保存查询结果。在这两个类中,仅声明表示层中所需的属性。然后使用Automapper将您的实体与ViewModel类映射。
之后,您可以执行以下查询:
var query =dbContext.Parents
.Include(p=>p.Children) // load the related entities as part of the query
.Where(p=>p.ParentName.Contains("test"))
.ProjectTo<ParentViewModel>();
Run Code Online (Sandbox Code Playgroud)
使用ProjectToAutomapper的扩展方法。
如您在上面引用的链接中所见,Automapper支持嵌套映射,因此,如果您具有ParentViewModel类型的属性,ICollection<ChildViewModel>并且还Child使用其ViewModel 映射了实体,则Automapper会自动尝试从一种类型映射到另一种类型。
所有这一切将在您的数据库中进行一次往返,因为这ProjectTo是一种IQueryable<TEntity>扩展方法,并且已转换为Select。
| 归档时间: |
|
| 查看次数: |
2534 次 |
| 最近记录: |