3

Мне нужно сопоставить объекты EF с соответствующими DTO. В приведенном ниже примере у меня есть объекты EF Родительский и дочерний, а дочерний объект содержит ссылку на родительский объект. У меня также есть ParentDto и ChildDto (DTO), а ChildDto содержит ссылку на ParentDto (не родительский). Итак, как я могу назначить 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

Вы должны использовать переменную, но вы не можете сделать это в лямбда-выражения. Вы должны сделать отображение в памяти после вызова 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-to-entity механизм создания объектов совершенно иная, инициализация логики может считаться идентичной, и применяются те же ограничения.

Как вы знаете, в LINQ-to-Entities мы не можем вызывать методы экземпляров объектов, пока мы находимся в выражении запроса. Например, вы могли бы, например, вызвать какой-то метод в Parent, который строит его дочерние элементы (и присваивает себе его как своего родителя). Как и сейчас, единственное, что вы можете сделать, это сначала построить Parent с их вложенными parent.Children, а затем переместить коллекции parent.Children и назначить им их Parent (как в ответе Уфука).

Смежные вопросы