Агрегатные операции

Последнее обновление: 21.11.2021

Entity Framework Core поддерживает ряд агрегатных операций, например, нахождение суммы по столбцу, количества элементов в выборке и т.д. Эти операции представлены такими методами как All, Any, Count, Sum, Min, Max, Average. Для рассмотрения агрегатных операций возьмем модели из прошлой темы:

using Microsoft.EntityFrameworkCore;
public class Company
{
    public int Id { get; set; }
    public string? Name { get; set; }
    public List<User> Users { get; set; } = new();
}

public class User
{
    public int Id { get; set; }
    public string? Name { get; set; }
    public int Age { get; set; }
    public int CompanyId { get; set; }
    public Company? Company { get; set; }
}
public class ApplicationContext : DbContext
{
    public DbSet<User> Users { get; set; } = null!; 
    public DbSet<Company> Companies { get; set; } = null!;

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlite("Data Source=helloapp.db");
    }
}

Наличие элементов

Метод Any() позволяет проверить, есть ли в базе данных элемент с определенными признаками, и если есть, то метод возвратит значение true. Например, проверим, есть ли в базе данных пользователи, которые работают в компании Google:

bool result = db.Users.Any(u=>u.Company!.Name=="Google");

При выполнении это выражение преобразуется в следующий SQL-запрос:

SELECT EXISTS (
	SELECT 1
    FROM "Users" AS "u"
    INNER JOIN "Companies" AS "c" ON "u"."CompanyId" = "c"."Id"
    WHERE "c"."Name" = 'Google')

Метод All() позволяет проверит, удовлетворяют ли все элементы в базе данных определенному критерию. Например, проверим, все ли пользователи работают в компании Microsoft:

bool result = db.Users.All(u=>u.Company!.Name=="Microsoft");

При вызове будет выполняться следующий SQL-запрос:

SELECT NOT EXISTS (
	SELECT 1
	FROM "Users" AS "u"
	INNER JOIN "Companies" AS "c" ON "u"."CompanyId" = "c"."Id"
	WHERE ("c"."Name" <> 'Microsoft') OR "c"."Name" IS NULL)

Количество элементов в выборке

Метод Count() позволяет найти количество элементов в выборке:

using(ApplicationContext db = new ApplicationContext())
{
    int number1 = db.Users.Count();
    // найдем кол-во пользователей, которые в имени содержат подстроку Tom
	int number2 = db.Users.Count(u => u.Name!.Contains("Tom"));

    Console.WriteLine(number1);
    Console.WriteLine(number2);
}

В результате будут выполняться варажения SQL наподобие:

SELECT COUNT(*)
FROM "Users" AS "u"

SELECT COUNT(*)
FROM Users AS u
WHERE ('Tom' == '') || (instr(u.Name, 'Tom') > 0))

Минимальное, максимальное и среднее значения

Для нахождения минимального, максимального и среднего значений по выборке применяются функции Min(), Max() и Average() соответственно. Найдем минимальный, максимальный и средний возраст пользователей:

using(ApplicationContext db = new ApplicationContext())
{
    // минимальный возраст
    int minAge = db.Users.Min(u=>u.Age);
    // максимальный возраст
    int maxAge = db.Users.Max(u=>u.Age);
    // средний возраст пользователей, которые работают в Microsoft
    double avgAge = db.Users.Where(u=>u.Company!.Name=="Microsoft")
						.Average(p => p.Age);

    Console.WriteLine(minAge);
    Console.WriteLine(maxAge);
    Console.WriteLine(avgAge);
}

Эти запросы трансформируются в SQLite в следующие SQL-выражения:

SELECT MIN("u"."Age")
FROM "Users" AS "u"

SELECT MAX("u"."Age")
FROM "Users" AS "u"

SELECT AVG(CAST("u"."Age" AS REAL))
FROM "Users" AS "u"
INNER JOIN "Companies" AS "c" ON "u"."CompanyId" = "c"."Id"
WHERE "c"."Name" = 'Microsoft'

Сумма значений

Для получения суммы значений используется метод Sum():

using(ApplicationContext db = new ApplicationContext())
{
	// суммарный возраст всех пользователей 
    int sum1 = db.Users.Sum(u => u.Age);
	// суммарный возраст тех, кто работает в Microsoft
    int sum2 = db.Users.Where(u=>u.Company!.Name == "Microsoft")
						.Sum(u => u.Age);
    Console.WriteLine(sum1);
    Console.WriteLine(sum2);
}

Во втором случае будет выполняться следующее SQL-выражение:

SELECT COALESCE(SUM("u"."Age"), 0)
FROM "Users" AS "u"
INNER JOIN "Companies" AS "c" ON "u"."CompanyId" = "c"."Id"
WHERE "c"."Name" = 'Microsoft'
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850