Cортировка и проекция из базы данных
Проекция
Проекция позволяет получить из набора объектов одного типа набор объектов другого типа.
Пусть у нас есть те же классы, что и в прошлой теме:
public class Company
{
public int Id { get; set; }
public string Name { get; set; }
public List<User> Users { get; set; } = new List<User>();
}
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<Company> Companies { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=helloappdb;Trusted_Connection=True;");
}
}
Допустим, нам надо добавить в результат выборки название компании. Мы можем использовать метод Include для подсоединения к объекту связанных данных из другой таблицы: var users = db.Users.Include(p=>p.Company)
. Но не всегда нужны все свойства выбираемых объектов. В этом случае мы можем применить метод Select для проекции извлеченных данных на новый тип:
using(ApplicationContext db = new ApplicationContext())
{
var users = db.Users.Select(p => new
{
Name = p.Name,
Age = p.Age,
Company = p.Company.Name
});
foreach (var user in users)
Console.WriteLine($"{user.Name} ({user.Age}) - {user.Company}");
}
В итоге метод Select из полученных данных спроецирует новый тип. При выполнении этот запрос будет трансформироваться в следующее выражение SQL:
SELECT [p].[Name], [p].[Age], [p.Company].[Name]
FROM [Users] AS [p]
INNER JOIN [Companies] AS [p.Company] ON [p].[CompanyId] = [p.Company].[Id]
В данном случае мы получим данные анонимного типа, но это также может быть определенный пользователем тип. Например:
public class Model
{
public string Name { get; set; }
public string Company { get; set; }
public int Age { get; set; }
}
И спроецируем выборку на этот тип:
var users = db.Users.Select(p => new Model
{
Name = p.Name,
Age = p.Age,
Company = p.Company.Name
});
foreach (Model user in users)
Console.WriteLine($"{user.Name} ({user.Age}) - {user.Company}");
Сортировка
Чтобы отсортировать полученные из БД данных по определенному критерию по возрастанию применяется метод OrderBy, либо оператор orderby. Например, отсортируем объекты по возрастанию по свойству Name:
using(ApplicationContext db = new ApplicationContext())
{
var users = db.Users.OrderBy(p=>p.Name);
foreach (var user in users)
Console.WriteLine($"{user.Id}.{user.Name} ({user.Age})");
}
В результате Entity Framework будет генерировать следующее выражение SQL, которое будет упорядочивать данные:
SELECT [u].[Id], [u].[CompanyId], [u].[Name], [u].[Age]
FROM [Users] AS [u]
ORDER BY [u].[Name]
В качестве альтернативы методу OrderBy можно использовать оператор orderby
:
var users = from u in db.Users
orderby u.Name
select u;
foreach (User user in users)
Console.WriteLine($"{user.Id}.{user.Name} ({user.Age})");
Для сортировки по убыванию применяется метод OrderByDescending():
var users = db.Users.OrderByDescending(u=>u.Name);
В этом случае к выражению SQL будет добавляться ключевое слово DESC:
SELECT [u].[Id], [u].[CompanyId], [u].[Name], [u].[Age]
FROM [Users] AS [u]
ORDER BY [u].[Name] DESC
При необходимости упорядочить данные сразу по нескольким критериям можно использовать методы ThenBy()(для сортировки по возрастанию) и ThenByDescending(). Например, отсортируем по двум значениям:
var users = db.Users.OrderBy(u => u.Age).ThenBy(u=>u.Company.Name);
Только полноправные пользователи могут оставлять комментарии. Аутентифицируйтесь пожалуйста, используя сервисы.