Linq 投影:获取新投影实体的参考
Linq projection: Get reference of new projected entity
我需要将 EF 实体映射到相应的 DTO。在下面的示例中,我有 EF 实体 Parent 和 Child,而 Child 实体包含对 Parent 对象的引用。我还有 ParentDto 和 ChildDto (DTO),并且 ChildDto 包含对 ParentDto(不是 Parent)的引用。那么,如何在以下方法中将 ParentDto 引用分配给 ChildDto 实例:
public Task<List<ParentDto>> Method()
{
return (Context.Set<Parent>()
.Where(someCondition)
.Select(p => new ParentDto
{
// here we map all properties from Parent to ParentDto
... ,
Children = p.Children.Select(c => new ChildDto
{
// here we map all properties from Child to ChildDto
... ,
Parent = ? // reference to newly created ParentDto instance
})
}).ToListAsync();
}
您必须使用变量,但不能在 lambda 表达式中使用。调用 ToListAsync()
:
后必须在内存中进行映射
public Task<List<ParentDto>> Method()
{
var parents = await (Context.Set<Parent>()
.Where(someCondition)
.ToListAsync());
return parents.Select(p =>
{
var parent = new ParentDto();
//map parent properties
parent.Children = p.Children.Select(c => new ChildrenDto
{
//map child properties
});
return parent;
}).ToList();
}
在常规 LINQ(不是实体)中这是不可能的,因为对象初始值设定项的一个重要特征:原子分配。如您所见,here,对象初始化如...
var c = new Customer() { Name = "Bart", City = "Redmond", Age = 24 };
...等同于...
Customer __t = new Customer();
__t.Name = "Bart";
__t.City = "Redmond";
__t.Age = 24;
Customer c = __t;
因此首先创建并完全初始化对象,然后公开其引用。因此,如果在对象内部初始化了另一个对象,则嵌套对象将永远无法在初始化阶段获取对其父对象的引用。您只能在之后分配父对象。
尽管在 LINQ-to-entities 中创建对象的机制完全不同,初始化 逻辑 可以被认为是相同的,并且适用相同的限制。
如您所知,在 LINQ-to-Entities 中,我们无法在查询表达式中调用实体的实例方法。否则,例如,您可以在 Parent
中调用一些方法来构造其子项(并将自己分配给它作为它们的父项)。就像现在一样,你唯一能做的就是先用嵌套的 parent.Children
构造 Parent
,然后遍历 parent.Children
集合并将它们的 Parent
分配给他们(如 Ufuk 的回答)。
我需要将 EF 实体映射到相应的 DTO。在下面的示例中,我有 EF 实体 Parent 和 Child,而 Child 实体包含对 Parent 对象的引用。我还有 ParentDto 和 ChildDto (DTO),并且 ChildDto 包含对 ParentDto(不是 Parent)的引用。那么,如何在以下方法中将 ParentDto 引用分配给 ChildDto 实例:
public Task<List<ParentDto>> Method()
{
return (Context.Set<Parent>()
.Where(someCondition)
.Select(p => new ParentDto
{
// here we map all properties from Parent to ParentDto
... ,
Children = p.Children.Select(c => new ChildDto
{
// here we map all properties from Child to ChildDto
... ,
Parent = ? // reference to newly created ParentDto instance
})
}).ToListAsync();
}
您必须使用变量,但不能在 lambda 表达式中使用。调用 ToListAsync()
:
public Task<List<ParentDto>> Method()
{
var parents = await (Context.Set<Parent>()
.Where(someCondition)
.ToListAsync());
return parents.Select(p =>
{
var parent = new ParentDto();
//map parent properties
parent.Children = p.Children.Select(c => new ChildrenDto
{
//map child properties
});
return parent;
}).ToList();
}
在常规 LINQ(不是实体)中这是不可能的,因为对象初始值设定项的一个重要特征:原子分配。如您所见,here,对象初始化如...
var c = new Customer() { Name = "Bart", City = "Redmond", Age = 24 };
...等同于...
Customer __t = new Customer();
__t.Name = "Bart";
__t.City = "Redmond";
__t.Age = 24;
Customer c = __t;
因此首先创建并完全初始化对象,然后公开其引用。因此,如果在对象内部初始化了另一个对象,则嵌套对象将永远无法在初始化阶段获取对其父对象的引用。您只能在之后分配父对象。
尽管在 LINQ-to-entities 中创建对象的机制完全不同,初始化 逻辑 可以被认为是相同的,并且适用相同的限制。
如您所知,在 LINQ-to-Entities 中,我们无法在查询表达式中调用实体的实例方法。否则,例如,您可以在 Parent
中调用一些方法来构造其子项(并将自己分配给它作为它们的父项)。就像现在一样,你唯一能做的就是先用嵌套的 parent.Children
构造 Parent
,然后遍历 parent.Children
集合并将它们的 Parent
分配给他们(如 Ufuk 的回答)。