【问题标题】:Linq projection: Get reference of new projected entityLinq 投影:获取新投影实体的参考
【发布时间】: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();
}

【问题讨论】:

    标签: entity-framework linq linq-to-entities entity-framework-6


    【解决方案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 的回答)。

      【讨论】:

        猜你喜欢
        • 2020-11-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多