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

Jawaban:


152

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

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


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();

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

7

Mungkin membantu, jika Anda ingin menambahkan beberapa filter:

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


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]

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()

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)

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.


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();
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.