Entity Framework Core (сокращенно EF Core) — это популярный ORM (объектно-реляционный преобразователь) от Microsoft, который позволяет вам выполнять операции CRUD (создавать, читать, обновлять и удалять), не зная, как данные сохраняются в базовом база данных.
При работе с ORM мы часто используем модели, сопоставленные с таблицами базы данных. Однако что, если у нас есть модель, которая не имитирует таблицу базы данных? Как мы можем отображать типы, не являющиеся сущностями, и заполнять объекты такой модели в наших приложениях? Мы можем сделать это с помощью типов запросов.
Первоначально представленные в EF Core 2.1, типы запросов — это типы (классы), не являющиеся сущностями, которые могут сопоставляться с таблицами или представлениями в базе данных без указания столбца идентификаторов, то есть с таблицами и представлениями, в которых отсутствует ключ. Типы запросов EF Core упрощают запросы к представлениям и типам моделей, для которых не требуются столбцы идентификаторов. Однако, поскольку для типов запросов не определен столбец идентификаторов, вы не можете вставлять, обновлять или удалять данные с их помощью. Вы можете использовать их только для получения данных.
Типы запросов позволяют указать сопоставление между запросом к базе данных и классами предметной области. Затем вы можете использовать один и тот же тип запроса с разными типами запросов EF Core, такими как LINQ to Entities или миграция EF Core.
В этой статье обсуждается, как мы можем использовать типы запросов EF Core в приложениях ASP.NET Core 7. Для работы с примерами кода, представленными в этой статье, в вашей системе должна быть установлена предварительная версия Visual Studio 2022. Если у вас еще нет копии, вы можете скачать Visual Studio 2022 здесь.
Создайте проект веб-API ASP.NET Core 7 в Visual Studio 2022.
Прежде всего, давайте создадим проект веб-API ASP.NET Core в Visual Studio 2022. Выполнив следующие действия, вы создадите новый проект веб-API ASP.NET Core в Visual Studio 2022:
- Запустите интегрированную среду разработки Visual Studio 2022.
- Нажмите «Создать новый проект».
- В окне «Создать новый проект» выберите «ASP.NET Core Web API» из списка отображаемых шаблонов.
- Нажмите “Далее.
- В окне «Настроить новый проект» укажите имя и расположение нового проекта.
- При желании установите флажок «Поместить решение и проект в один каталог», в зависимости от ваших предпочтений.
- Нажмите “Далее.
- В окне «Дополнительная информация», показанном далее, в разделе Framework выберите .NET 7.0.
- Оставьте флажок «Использовать контроллеры…», поскольку в этом примере мы будем использовать контроллеры. Оставьте для параметра «Тип аутентификации» значение «Нет» (по умолчанию).
- Убедитесь, что флажки «Включить Docker», «Настроить для HTTPS» и «Включить поддержку Open API» не отмечены, так как мы не будем использовать эти функции здесь.
- Щелкните Создать.
Мы будем использовать этот проект веб-API ASP.NET Core 7 для работы с типами запросов EF Core в последующих разделах этой статьи.
Работа с типами запросов в ASP.NET Core 7
Давайте начнем с создания некоторых сущностей, которые мы можем запрашивать. В нашем примере мы будем использовать следующие два класса: Учитель и Пакет.
public class Teacher
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public ICollection<Batch> Batches { get; set; }
}
public class Batch
{
public int Id { get; set; }
public string Title { get; set; }
public int NoOfStudents { get; set; }
public int TeacherId { get; set; }
}
Создайте представление в своей базе данных
Теперь создайте в своей базе данных представление с именем BatchDetails, используя следующий код. Мы будем использовать типы запросов для сопоставления с этим представлением.
Create View BatchDetails AS
Select t.FirstName, t.LastName, t.BatchTitle, t.NoOfStudents as Total_Students
From Teacher t
Join Batch b on b.Id = t.Id
Нам также понадобится класс, который можно использовать для хранения данных, полученных из только что созданного представления. В следующем фрагменте кода показано, как можно создать класс с именем BatchDetails для хранения данных, запрашиваемых из представления.
public class BatchDetails
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Title { get; set; }
public int NoOfStudents { get; set; }
}
Настройте тип запроса в EF Core.
У вас есть два способа настроить тип запроса. Если вы не хотите загромождать свой DbContext, вы можете создать свой класс DbContext как разделяемый класс, а затем полностью разделить объявление DbQuery в отдельный файл.
Вот содержимое файла DemoDbContext.cs:
public partial class DemoDbContext : DbContext
{
public DbSet<Teacher> Teachers { get; set; }
public DbSet<Batch> Batches { get; set; }
}
А вот содержимое файла DemoDbContextQuery.cs:
public partial class DemoDbContext : DbContext
{
public DbQuery<BatchDetails> Batches { get; set; }
}
Вы должны настроить тип запроса в методе OnModelCreating, как показано во фрагменте кода, приведенном ниже.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Query<BatchDetails>().ToView("BatchDetails");
}
Создайте репозиторий в ASP.NET Core
Теперь мы создадим репозиторий для чтения данных из базы данных. Обратите внимание, что хотя репозиторий будет напрямую взаимодействовать с базой данных, контроллер будет использовать репозиторий для получения данных. (Мы реализуем контроллер в следующем разделе.)
Создайте файл с именем IBatchRepository.cs со следующим кодом. IBatchRepository будет служить интерфейсом для нашего BatchDetailsRepository.
public interface IBatchDetailsRepository
{
public List<BatchDetails> GetBatchDetails();
}
Создайте еще один файл с именем BatchDetailsRepository.cs и введите следующий код, чтобы создать класс репозитория.
public class BatchDetailsRepository: IBatchDetailsRepository
{
private DemoDbContext dbContext;
public BatchDetailsRepository(DemoDbContext demoDbContext)
{
dbContext = demoDbContext;
}
public List<BatchDetails> GetBatchDetails()
{
return dbContext.BatchDetails.ToList();
}
}
Создайте контроллер API в ASP.NET Core.
Теперь создайте контроллер API с именем BatchDetailsController в файле с тем же именем и расширением .cs. Затем напишите туда следующий код.
[Route("api/[controller]")]
[ApiController]
public class BatchDetailsController : ControllerBase
{
private IBatchDetailsRepository _batchDetailsRepository;
public BatchDetailsController(IBatchDetailsRepository
batchDetailsRepository)
{
_batchDetailsRepository = batchDetailsRepository;
}
[HttpGet]
public IActionResult Get()
{
return Ok(_batchDetailsRepository.GetBatchDetails());
}
}
Обратитесь к предыдущему листингу кодов. Обратите внимание, как внедрение зависимостей использовалось для внедрения экземпляра типа IBatchDetailsRepository в конструктор класса BatchDetailsController.
Вы можете возвращать типы запросов из необработанных запросов SQL, используя метод FromSql в типе DbQuery, и они также могут участвовать в отношениях.
Наконец, следует помнить о двух ограничениях типов запросов. Как упоминалось выше, поскольку типы запросов нельзя отслеживать по контексту, вы можете использовать их только для чтения, а не для записи. И вы не можете использовать методы Add и Attach DbContext при работе с типами запросов.