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.?

답변:


154

이 시도 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 (); if (model! = null) {var val = db.BillOfLading.Max (x => x.No);
HerGiz

이것이 효율적입니까? 아니면 엔터티 프레임 워크가 Max 함수를 사용하는 저장 프로 시저를 실행하도록하는 것이 더 낫습니까? 엔터티 프레임 워크를 처음
TemporaryFix

@Programmatic은 더 효율적일 이유가 전혀 없습니다. Sql Server 버전 <= 7 제외
mxmissile

52

목록이 비어 있으면 예외가 발생합니다. 이 솔루션은 다음 문제를 고려합니다.

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

7
이것은 받아 들여진 대답이어야합니다. 서버까지 한 번만 왕복하며 예외는 없습니다.
9Rune5 2017-04-20

4
그러나 데이터베이스에서 모든 열 값을 검색하고 응용 프로그램 측에 Max를 적용합니다.
SuperDuck 19-01-23

2
이렇게하면 3 개의 하위 쿼리가 생성됩니다. 나는 다른 대답을 제안했다.
jsgoupil

4
참고로 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

열은 nullable입니다.

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]

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을 보면 두 번째 대답이 좋습니다.
Deepak Sharma

2

에서 VB.Net 는 것

Dim maxAge As Integer = context.Persons.Max(Function(p) p.Age)

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

목록이 비어있는 경우이 버전 :

  • nullnullable 오버로드에 대해 ―를 반환합니다.
  • 예외 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와 함께 작동합니다. nullable이 아닌 형식을 nullable로 캐스팅 한 다음 ??연산자를 사용하여 기본값을 적용하여 위에서 언급 한 예외를 처리합니다 .


1

선택한 답변은 예외를 throw하고 Carlos Toledo의 답변은 데이터베이스에서 모든 값을 검색 한 후 필터링을 적용합니다.

다음은 단일 왕복을 실행하고 예외없이 가능한 모든 인덱스를 사용하여 단일 값을 읽습니다.

int maxAge = _dbContext.Persons
  .OrderByDescending(p => p.Age)
  .Select(p => p.Age)
  .FirstOrDefault();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.