Язык программирования C#9 и платформа .NET5
Класс
реализует интерфейсDbSet<T>и обычно является целью запросов LINQ to Entity. Помимо расширяющих методов, добавленных инфраструктурой EF Core, классIQueryable<T>поддерживает расширяющие методы, которые вы изучили в главе 13, такие какDbSet<T>,ForEach()иSelect().All()Вы узнаете, как добавлять к классу
свойства типаApplicationDbContext, в разделе "Сущности" далее в главе.DbSet<T>На заметку! Многие методы из перечисленных в табл. 22.2, имеют те же самые имена, что и методы в табл. 22.1. Основное отличие в том, что методам
уже известен тип, с которым нужно работать, и список сущностей. МетодыDbSet<T>обязаны определять, на чем действовать, с применением рефлексии. МетодыDbContextиспользуются гораздо чаще, чем методыDbSet<T>.DbContextТипы запросов
Типы запросов — это коллекции
, которые применяются для изображения представлений, оператора SQL или таблиц без первичного ключа. В предшествующих версиях EF Core для всего упомянутого использовался типDbSet<T>, но начиная с EF Core 3.1, типDbQuery<T>больше не употребляется. Типы запросов добавляются к производному классуDbQueryс применением свойствDbContextи конфигурируются как не имеющие ключей.DbSet<T>Например, класс
(который вы создадите при построении полной библиотеки доступа к даннымCustomerOrderViewModel) конфигурируется с атрибутомAutoLot:[Keyless]<b>[Keyless]</b>public class CustomerOrderViewModel{...}Остальные действия по конфигурированию делаются в Fluent API. В следующем примере сущность устанавливается как не имеющая ключа, а тип запроса сопоставляется с представлением базы данных
(обратите внимание, что вызов методdbo.CustomerOrderViewиз Fluent API не требуется, если в модели присутствует аннотация данныхHasNoKey(), и наоборот, но он показан ради полноты):KeylessmodelBuilder.Entity<CustomerOrderViewModel>().HasNoKey().ToView("CustomerOrderView", "dbo");Типы запросов могут также сопоставляться с запросом SQL, как показано ниже:
modelBuilder.Entity<CustomerOrderViewModel>().HasNoKey().ToSqlQuery(@"SELECT c.FirstName, c.LastName, i.Color, i.PetName, m.Name AS MakeFROM dbo.Orders oINNER JOIN dbo.Customers c ON o.CustomerId = c.IdINNER JOIN dbo.Inventory i ON o.CarId = i.IdINNER JOIN dbo.Makes m ON m.Id = i.MakeId");Последние механизмы, с которыми можно использовать типы запросов — это методы
иFromSqlRaw(). Вот пример того же самого запроса, но с применениемFromSqlInterpolated():FromSqlRaw()public IEnumerable<CustomerOrderViewModel> GetOrders(){return CustomerOrderViewModels.FromSqlRaw(@"SELECT c.FirstName, c.LastName, i.Color, i.PetName, m.Name AS MakeFROM dbo.Orders oINNER JOIN dbo.Customers c ON o.CustomerId = c.IdINNER JOIN dbo.Inventory i ON o.CarId = i.IdINNER JOIN dbo.Makes m ON m.Id = i.MakeId");}Гибкое сопоставление с запросом или таблицей
В версии EF Core 5 появилась возможность сопоставления одного и того же класса с более чем одним объектом базы данных. Такими объектами могут быть таблицы, представления или функции. Например, класс
из главы 21 может отображаться на представление, которое возвращает название производителя с даннымиCarViewModelи таблицей Inventory. Затем EF Core будет запрашивать из представления и отправлять обновления таблице:CarmodelBuilder.Entity<CarViewModel>().ToTable("Inventory").ToView("InventoryWithMakesView");Экземпляр ChangeTracker
Экземпляр
отслеживает состояние объектов, загруженных вChangeTrackerвнутри экземпляраDbSet<T>. В табл. 22.3 описаны возможные значения для состояния объекта.DbContextДля проверки состояния объекта используйте следующий код:
EntityState state = context.Entry(entity).State;Вы также можете программно изменять состояние объекта с применением того же самого механизма. Чтобы изменить состояние на
, используйте такой код:Deletedcontext.Entry(entity).State = EntityState.Deleted;События ChangeTracker
Экземпляр
способен генерировать два события:ChangeTrackerиStateChanged. СобытиеTrackedинициируется в случае изменения состояния сущности. Оно не генерируется при отслеживании сущности в первый раз. СобытиеStateChangedинициируется, когда сущность начинает отслеживаться, либо за счет добавления экземпляраTrackedв коде, либо при возвращении из запроса.DbSet<T>

