#c# #entity-framework #entity-framework-core
Вопрос:
Можно ли выделить две строки в один анонимный объект DTO с двумя свойствами? С такой моделью, как:
public class Document
{
public int Id { get; set; }
public string Text { get; set; }
// Other properties
}
Я пишу метод, который находит разницу между двумя версиями документа:
public Task<string> CompareVersions(int initialId, int finalId)
Поэтому мне нужно получить текст ровно двух Documents
по идентификатору, и мне нужно знать, кто из них был кем.
В настоящее время я строю Dictionary<int, string>
, делая:
var dto = await _context.Documents
.Where(doc => doc.Id == initialId
|| doc.Id == finalId)
.ToDictionaryAsync(x => x.Id, x => x.Text);
а потом позвонил dto[initialId]
, чтобы получить сообщение. Однако это кажется очень громоздким. Есть ли какой-либо способ взять два идентификатора и выбрать их в один DTO в форме
{
InitialText,
FinalText
}
Ответ №1:
Вы должны использовать SelectMany
var query =
from initial in _context.Documents
where initial.Id = initialId
from final in _context.Documents
where final.Id = finalId
select new
{
InitialText = initial.Text,
FinalText = final.Text
};
var result = await query.FirstOrDefaultAsync();
Комментарии:
1. Хотя я предпочитаю стиль lambda стилю запросов, эта версия настолько элегантнее, что я с радостью приму ее.
Ответ №2:
Aggregate тоже может это сделать
var dto = (await _context.Documents
.Where(doc => doc.Id == initialId || doc.Id == finalId).ToListAsync())
.Aggregate(
new { InitialText = "", FinalText = "" },
(seed, doc) => {
if(doc.Id == initialId)
seed.InitialText = doc.Text;
else
seed.FinalText = doc.Text;
}
);
Я не уверен, что мне это нравится больше, чем ваш подход к составлению словаря, но с фактическим dto в конце, а не со словарем:
var d = await _context.Documents
.Where(doc => doc.Id == initialId || doc.Id == finalId)
.ToDictionaryAsync(x => x.Id, x => x.Text);
var dto = new { InitialText = d[initialId], FinalText = d[finalId] };
Вы также могли бы, возможно, просто:
var dto = new {
InitialText = await context.Documents
.FindAsync(initialId),
FinalText = await context.Documents
.FindAsync(finalId)
};