3

我需要将EF实体映射到各自的DTO。在下面的例子中,我有EF实体Parent和Child,而Child实体包含对Parent对象的引用。我也有ParentDto和ChildDto(DTO),而ChildDto包含对ParentDto(不是Parent)的引用。所以,我怎么能在下面的方法分配ParentDto参考ChildDto例如:Linq投影:获取新投影实体的参考

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(); 
} 
1

在常规的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到实体创建对象的机制是完全不同的,初始化逻辑可以被认为是相同的,并且相同的限制适用。

如您所知,在LINQ-to-Entities中,我们无法在查询表达式中调用实体的实例方法。否则,例如,您可以在Parent中调用一些方法来构造其子元素(并将其作为其父元素)。现在,唯一可以做的事情是先构造Parent,并首先嵌套parent.Children,然后遍历parent.Children集合,并将它们的Parent分配给它们(如Ufuk的回答)。