Как получить максимальное значение столбца с помощью Entity Framework?

92

Чтобы получить максимальное значение столбца, содержащего целое число, я могу использовать следующую команду T-SQL

SELECT MAX(expression )
FROM tables
WHERE predicates;

Можно ли получить такой же результат с Entity Framework.

Допустим, у меня есть следующая модель

public class Person
{
  public int PersonID { get; set; }
  public int Name { get; set; }
  public int Age { get; set; }
}

Как узнать возраст самого старшего человека?

int maxAge = context.Persons.?
Ричард77
источник

Ответы:

152

Попробуй это int maxAge = context.Persons.Max(p => p.Age);

И убедитесь, что using System.Linq;вверху вашего файла

кролик
источник
2
Я немного боролся с этим, потому что я пропустил "using System.Linq;" Вам следует подумать о добавлении этой информации в свой ответ таким новичкам, как я :)
RagnaRock
2
Нет проблем @RagnaRock
krolik
3
Но что, если у вас нет записей и EF выдает ошибки. Мое дополнение var model = db.BillOfLading.Select (x => x.No) .LastOrDefault (); если (модель! = null) {var val = db.BillOfLading.Max (x => x.No);
HerGiz
Это эффективно? Или было бы лучше, если бы Entity Framework выполняла хранимую процедуру, которая использует функцию Max? Новичок в Entity framework и мне искренне любопытно
TemporaryFix
@Programmatic абсолютно нет причин, по которым было бы более эффективно. За исключением версии Sql Server <= 7.
mxmissile
49

Если список пуст, я получаю исключение. Это решение учтет эту проблему:

int maxAge = context.Persons.Select(p => p.Age).DefaultIfEmpty(0).Max();
Карлос Толедо
источник
7
Это должен быть принятый ответ. Только одно обращение к серверу и без исключений.
9Rune5
4
Но он извлекает все значения столбцов из базы данных и применяет Max на стороне приложения.
SuperDuck
1
Это делает 3 подзапроса. Я предложил другой ответ.
jsgoupil
3
просто примечание - это не работает с ядром EF. Я использовал:await _context.Persons.MaxAsync(x => (int?)x.Age) ?? 0
egmfrs
11

Или вы можете попробовать это:

(From p In context.Persons Select p Order By age Descending).FirstOrDefault
Даникод
источник
7

Может быть, поможет, если вы хотите добавить фильтр:

context.Persons
.Where(c => c.state == myState)
.Select(c => c.age)
.DefaultIfEmpty(0)
.Max();
Фой
источник
4
maxAge = Persons.Max(c => c.age)

Или что-то вдоль этих линий.

Э.Дж. Бреннан
источник
4

Ваш столбец допускает значение NULL

int maxAge = context.Persons.Select(p => p.Age).Max() ?? 0;

Ваш столбец не допускает значения NULL

int maxAge = context.Persons.Select(p => p.Age).Cast<int?>().Max() ?? 0;

В обоих случаях вы можете использовать второй код. Если вы используете DefaultIfEmpty, вы будете делать больший запрос на своем сервере. Для тех, кому интересно, вот эквивалент EF6:

Запрос без DefaultIfEmpty

SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        MAX([Extent1].[Age]) AS [A1]
        FROM [dbo].[Persons] AS [Extent1]
    )  AS [GroupBy1]

Запрос с DefaultIfEmpty

SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        MAX([Join1].[A1]) AS [A1]
        FROM ( SELECT 
            CASE WHEN ([Project1].[C1] IS NULL) THEN 0 ELSE [Project1].[Age] END AS [A1]
            FROM   ( SELECT 1 AS X ) AS [SingleRowTable1]
            LEFT OUTER JOIN  (SELECT 
                [Extent1].[Age] AS [Age], 
                cast(1 as tinyint) AS [C1]
                FROM [dbo].[Persons] AS [Extent1]) AS [Project1] ON 1 = 1
        )  AS [Join1]
    )  AS [GroupBy1]
jsgoupil
источник
1
Что насчетint maxAge = context.Persons.Max(x => (int?)x.Age) ?? 0;
egmfrs
3

Как многие говорили - эта версия

int maxAge = context.Persons.Max(p => p.Age);

выдает исключение, когда таблица пуста.

Использовать

int maxAge = context.Persons.Max(x => (int?)x.Age) ?? 0;

или

int maxAge = context.Persons.Select(x => x.Age).DefaultIfEmpty(0).Max()
АК
источник
ваш второй ответ мне нравится, если кто-то посмотрит на сгенерированный SQL, второй ответ будет хорош.
Дипак Шарма
2

В VB.Net это было бы

Dim maxAge As Integer = context.Persons.Max(Function(p) p.Age)
дипи зло
источник
2
int maxAge = context.Persons.Max(p => p.Age);

Эта версия, если список пуст :

  • Возвраты null- для перегрузок, допускающих значение NULL
  • Выдает Sequence contains no elementисключение - для перегрузок, не допускающих значения NULL

-

int maxAge = context.Persons.Select(p => p.Age).DefaultIfEmpty(0).Max();

Эта версия обрабатывает случай пустого списка, но генерирует более сложный запрос и по какой-то причине не работает с EF Core.

-

int maxAge = context.Persons.Max(p => (int?)p.Age) ?? 0;

Эта версия элегантна и производительна (простой запрос и одно обращение к базе данных), работает с EF Core. Он обрабатывает упомянутое выше исключение, преобразуя тип, не допускающий значение NULL, к типу, допускающему значение NULL, а затем применяет значение по умолчанию с помощью ??оператора.

Seidme
источник
1

Выбранный ответ вызывает исключения, а ответ Карлоса Толедо применяет фильтрацию после извлечения всех значений из базы данных.

Следующий запускает один цикл и считывает одно значение с использованием любых возможных индексов без исключения.

int maxAge = _dbContext.Persons
  .OrderByDescending(p => p.Age)
  .Select(p => p.Age)
  .FirstOrDefault();
SuperDuck
источник