Выберите свойство из повторяющихся записей в ef core linq

#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, где в основном успешно работает все, что компилируется.