#c# #linq #entity-framework-core
Вопрос:
У меня есть база данных, содержащая дубликаты записей, но только их поле идентификатора совпадает, а остальная информация отличается, например:
Id: test, version: 1.0.0
Id: test, version: 2.1.3
Id: something, version: 4.0.0
Id: something, version: 5.0.0
...
Я могу получить все товары без дублирования со следующими кодами
using var db = new dbContext();
var query =
from item in db.my.Select(x => new { x.Id }).Distinct()
.SelectMany(key => db.myTable.Where(x => x.Id == key.Id).Take(1))
select new myModel
{
Id = item.Id,
Versions = <Here we need all related versions>
};
return await query.ToListAsync();
Теперь я хочу получить все версии идентификатора и поместить его в Versions
select new myModel{}
Но я не знаю, как это сделать
ОБНОВЛЕНИЕ: я добавил эту строку в запрос
from versions in db.myTable.AsEnumerable().GroupBy(x => x.Id)
и
select new myModel
{
Id = item.Id,
Versions = versions.Select(x => x.Version).ToList()
};
но я получил ошибку
System.InvalidOperationException: 'Processing of the LINQ expression 'GroupByShaperExpression:
Комментарии:
1. Что такое
Versions
? Если это списокmy
экземпляров класса сущностей, то переключитесь обратно на исходное решение сGroupBy
помощью функции выполнено в памяти (AsEnumerable().GroupBy(...)
). Решение для предыдущего вопроса состояло в том, чтобы возвращать один товар за единицуId
. Хорошо заранее знать, что именно вам нужно в результате, так как, к сожалению, подходы разные.2. Версии-это список<Строка>, Как вы ответили в предыдущем посте, Теперь, кроме того, я хочу получить версии каждого идентификатора
3. Я имею в виду, что мне нужно и то, и другое, не дублирующий список, и каждый элемент со своей собственной версией
4. Так что сделайте это в памяти, как предложено в другом ответе. В любом случае, слишком много вопросов для такой простой задачи.
5. @SvyatoslavDanyliv я обновил свой вопрос, я использовал метод памяти, но получил ошибку. Ваш метод и метод памяти, похоже, не сочетаются
Ответ №1:
Для этого требуется иной подход, чем для возврата одного элемента в группу.
Требуемая операция здесь не имеет смысла реализовываться на стороне сервера, следовательно, должна выполняться на стороне клиента, с единственной потенциальной оптимизацией, заключающейся в том, чтобы не извлекать ненужные данные из базы данных.
Во-первых, используйте запрос на стороне сервера, чтобы выбрать все необходимые данные. Затем материализуйте этот запрос в памяти и выполните GroupBy
там окончательную проекцию.
напр.
var dbQuery = db.my.Select(x => new
{
x.Id,
x.Version,
});
var data = await dbQuery.ToListAsync();
var result = data
.GroupBy(x => x.Id)
.Select(g => new myModel
{
Id = g.Key,
Versions = g.Select(x => x.Version).ToList(),
});
Комментарии:
1. спасибо, и если я хочу получить другие поля, такие как имя, я должен написать это?
Name = g.Select(x => x.Name).First(),
2. Да, ты мог бы. Все, что происходит после выполнения запроса к БД и сохранения результата в памяти, выполняется в обычном контексте LINQ to Objects, где в основном успешно работает все, что компилируется.