Linq 投影:获取新投影实体的参考

Posted

技术标签:

【中文标题】Linq 投影:获取新投影实体的参考【英文标题】:Linq projection: Get reference of new projected entity 【发布时间】:2015-12-25 17:41:28 【问题描述】:

我需要将 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();

【问题讨论】:

【参考方案1】:

您必须使用变量,但不能在 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();

【讨论】:

【参考方案2】:

在常规 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 构造Parents,然后遍历parent.Children 集合并将它们的Parent 分配给它们(如Ufuk 的回答)。

【讨论】:

以上是关于Linq 投影:获取新投影实体的参考的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data JPA 通过查询从实体获取投影

Linq:在进行投影时设置属性

如何创建可重用的实体框架投影表达式?

投影查询:如何使用 JPA 为 AppEngine 中的新实体加载原始字符串?

Spring-data-jpa 投影生成查询不正确

反向地图投影:如何从投影坐标中获取纬度/经度坐标