Bagaimana cara mendapatkan nilai maksimal kolom menggunakan Entity Framework?

92

Untuk mendapatkan nilai maksimal dari kolom yang berisi integer, saya dapat menggunakan perintah T-SQL berikut

SELECT MAX(expression )
FROM tables
WHERE predicates;

Apakah mungkin untuk mendapatkan hasil yang sama dengan Entity Framework.

Katakanlah saya memiliki model berikut

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

Bagaimana cara mengetahui usia orang tertua?

int maxAge = context.Persons.?
Richard77
sumber

Jawaban:

152

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

Dan pastikan Anda memiliki using System.Linq;di bagian atas file Anda

krolik
sumber
2
Saya berjuang sedikit dengan ini karena saya melewatkan "using System.Linq;" Anda harus mempertimbangkan untuk menambahkan info itu ke jawaban Anda untuk pemula seperti saya :)
RagnaRock
2
Tidak masalah @RagnaRock
krolik
3
Tetapi bagaimana jika Anda tidak memiliki catatan dan kesalahan trows EF. Model var tambahan saya = db.BillOfLading.Select (x => x.No) .LastOrDefault (); if (model! = null) {var val = db.BillOfLading.Max (x => x.No);
HerGiz
Apakah ini efisien? Atau akankah lebih baik jika kerangka entitas menjalankan prosedur tersimpan yang menggunakan fungsi Max? Baru mengenal framework entitas dan saya benar-benar penasaran
TemporaryFix
@Programmatic sama sekali tidak ada alasan yang akan lebih efisien. Kecuali pada Sql Server versi <= 7.
mxmissile
49

Jika daftar kosong saya mendapatkan pengecualian. Solusi ini akan mempertimbangkan masalah ini:

int maxAge = context.Persons.Select(p => p.Age).DefaultIfEmpty(0).Max();
Carlos Toledo
sumber
7
Ini harus menjadi jawaban yang diterima. Hanya satu perjalanan bolak-balik ke server dan tidak ada pengecualian.
9Rune5
4
Tapi itu mengambil semua nilai kolom dari database, dan menerapkan Max di sisi aplikasi.
SuperDuck
1
Ini membuat 3 sub-kueri. Saya mengusulkan jawaban yang berbeda.
jsgoupil
3
hanya catatan tambahan - ini tidak berfungsi dengan inti EF. Saya menggunakan:await _context.Persons.MaxAsync(x => (int?)x.Age) ?? 0
egmfrs
11

Atau Anda dapat mencoba ini:

(From p In context.Persons Select p Order By age Descending).FirstOrDefault
danicode
sumber
7

Mungkin membantu, jika Anda ingin menambahkan beberapa filter:

context.Persons
.Where(c => c.state == myState)
.Select(c => c.age)
.DefaultIfEmpty(0)
.Max();
Foy
sumber
4
maxAge = Persons.Max(c => c.age)

atau sesuatu seperti itu.

EJ Brennan
sumber
4

Kolom Anda tidak dapat diisi

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

Kolom Anda tidak dapat dinihilkan

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

Dalam kedua kasus tersebut, Anda dapat menggunakan kode kedua. Jika Anda menggunakanDefaultIfEmpty , Anda akan melakukan kueri yang lebih besar di server Anda. Untuk orang yang tertarik, berikut adalah EF6 yang setara:

Kueri tanpa DefaultIfEmpty

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

Kueri dengan 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.dll
sumber
1
Bagaimana denganint maxAge = context.Persons.Max(x => (int?)x.Age) ?? 0;
egmfrs
3

Seperti yang dikatakan banyak orang - versi ini

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

melempar pengecualian saat tabel kosong.

Menggunakan

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

atau

int maxAge = context.Persons.Select(x => x.Age).DefaultIfEmpty(0).Max()
AK
sumber
jawaban kedua Anda terlihat bagus bagi saya, jika seseorang melihat SQL yang dihasilkan, jawaban kedua bagus.
Deepak Sharma
2

Di VB.Net itu akan

Dim maxAge As Integer = context.Persons.Max(Function(p) p.Age)
dipi jahat
sumber
2
int maxAge = context.Persons.Max(p => p.Age);

Versi ini, jika daftarnya kosong :

  • Returns null- untuk kelebihan beban nullable
  • Melempar Sequence contains no elementpengecualian - untuk kelebihan beban yang tidak dapat dinolkan

-

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

Versi ini menangani kasus daftar kosong, tetapi menghasilkan kueri yang lebih kompleks, dan untuk beberapa alasan tidak berfungsi dengan EF Core.

-

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

Versi ini elegan dan berkinerja baik (kueri sederhana dan sekali jalan pulang pergi ke database), bekerja dengan EF Core. Ini menangani pengecualian yang disebutkan di atas dengan mentransmisikan tipe non-nullable ke nullable dan kemudian menerapkan nilai default menggunakan ??operator.

seidme
sumber
1

Jawaban yang dipilih melontarkan pengecualian, dan jawaban dari Carlos Toledo menerapkan pemfilteran setelah mengambil semua nilai dari database.

Yang berikut menjalankan satu perjalanan bolak-balik dan membaca satu nilai, menggunakan indeks apa pun yang memungkinkan, tanpa pengecualian.

int maxAge = _dbContext.Persons
  .OrderByDescending(p => p.Age)
  .Select(p => p.Age)
  .FirstOrDefault();
SuperDuck
sumber