Новые возможности EF Core 2.1
Помимо многочисленных исправлений ошибок и небольших функциональных и повышения производительности, EF Core 2.1 включает некоторые убедительные новые функции:
Отложенная загрузка
EF Core теперь содержит необходимые стандартные блоки для всех, кто создает классы сущностей, которые могут загружать их свойства навигации по запросу. Мы также создали новый пакет Microsoft.EntityFrameworkCore.Proxies, который использует эти стандартные блоки для создания отложенной загрузки прокси-классов на основе минимально измененных классов сущностей (например, классов с свойствами виртуальной навигации).
Для получения дополнительной информации об этой теме см. раздел о ленивой загрузке.
Параметры в конструкторах сущностей
В качестве одного из обязательных стандартных блоков для отложенной загрузки мы включили создание сущностей, которые принимают параметры в своих конструкторах. Можно использовать параметры для внедрения значений свойств, делегатов с отложенной загрузкой и сервисов.
Читайте раздел о конструкторе сущностей с параметрами для получения дополнительной информации по этой теме.
Преобразования значений
До сих пор EF Core может сопоставлять только свойства типов, которые изначально поддерживаются базовым поставщиком баз данных. Значения были скопированы обратно и вперед между столбцами и свойствами без какого-либо преобразования. Начиная с EF Core 2.1 преобразования значений можно применять для преобразования значений, полученных из столбцов, прежде чем они применяются к свойствам, и наоборот. У нас есть ряд преобразований, которые могут применяться по соглашению при необходимости, а также явный API конфигурации, который позволяет регистрировать пользовательские преобразования между столбцами и свойствами. Некоторые из приложений этой функции:
- Хранение перечислений в виде строк
- Сопоставление целых чисел без знака в SQL Server
- Автоматическое шифрование и расшифровка значений свойств
Для получения дополнительной информации об этой теме см. раздел о преобразовании значений.
Перевод LINQ GroupBy
До версии 2.1 в EF Core оператор GroupBy LINQ всегда будет оцениваться в памяти. Теперь мы поддерживаем преобразование его в предложение SQL GROUP BY в большинстве распространенных случаев.
В этом примере показан запрос с GroupBy, используемый для вычисления различных агрегатных функций:
var query = context.Orders
.GroupBy(o => new { o.CustomerId, o.EmployeeId })
.Select(g => new
{
g.Key.CustomerId,
g.Key.EmployeeId,
Sum = g.Sum(o => o.Amount),
Min = g.Min(o => o.Amount),
Max = g.Max(o => o.Amount),
Avg = g.Average(o => o.Amount)
});
Соответствующий перевод SQL выглядит следующим образом:
SELECT [o].[CustomerId], [o].[EmployeeId],
SUM([o].[Amount]), MIN([o].[Amount]), MAX([o].[Amount]), AVG([o].[Amount])
FROM [Orders] AS [o]
GROUP BY [o].[CustomerId], [o].[EmployeeId];
Заполнение данными
В новом выпуске можно будет предоставить начальные данные для заполнения базы данных. В отличие от EF6, начальные данные связаны с типом сущности в рамках конфигурации модели. Затем миграции EF Core могут автоматически вычислять операции вставки, обновления или удаления, которые необходимо применить при обновлении базы данных до новой версии модели.
Например, это можно использовать для настройки начальных данных для сообщения в OnModelCreating
.
modelBuilder.Entity<Post>().HasData(new Post{ Id = 1, Text = "Hello World!" });
Читайте раздел о заполнении данных для получения дополнительной информации об этой теме.
Типы запросов
Теперь модель EF Core может включать типы запросов. В отличие от типов сущностей, типы запросов не определяют ключи и не могут быть вставлены, удалены или обновлены (т. е. они доступны только для чтения), но их можно возвращать непосредственно запросами. Ниже приведены некоторые сценарии использования типов запросов:
- Сопоставление представлений без первичных ключей
- Сопоставление таблиц без первичных ключей
- Сопоставление с запросами, определенными в модели
- Выступает в качестве возвращаемого типа для запросов
FromSql()
См. раздел о типах запросов для получения дополнительной информации о данной теме.
Включать для производных типов
Теперь можно будет указать свойства навигации, определенные только для производных типов при написании выражений для метода Include
. Для строго типизированной версии Include
можно использовать либо явное приведение, либо оператор as
. Теперь мы также поддерживаем ссылки на имена навигационных свойств, определенных для производных типов в строковой версии Include
.
var option1 = context.People.Include(p => ((Student)p).School);
var option2 = context.People.Include(p => (p as Student).School);
var option3 = context.People.Include("School");
Дополнительные сведения по этой теме см. в разделе "Включение производных типов".
Поддержка для System.Transactions
Мы добавили возможность работать с функциями System.Transactions, такими как TransactionScope. Это будет работать как на платформе .NET Framework, так и в .NET Core при использовании поставщиков баз данных, поддерживающих ее.
Дополнительные сведения об этой теме см. в секции System.Transactions.
Улучшение порядка столбцов при первоначальной миграции
На основе отзывов клиентов мы обновили миграции для первоначального создания столбцов для таблиц в том же порядке, что и свойства, объявленные в классах. Обратите внимание, что EF Core не может изменить порядок при добавлении новых элементов после создания начальной таблицы.
Оптимизация коррелированных подзапросов
Мы улучшили перевод запросов, чтобы избежать выполнения запросов "N+ 1" SQL во многих распространенных сценариях, в которых использование свойства навигации в проекции приводит к присоединению данных из корневого запроса с данными из коррелированного подзапроса. Для оптимизации требуется буферизация результатов из субзапроса, и вы должны изменить запрос, чтобы включить новое поведение.
Например, следующий запрос обычно преобразуется в один запрос для клиентов, а также N (где "N" — это число возвращенных клиентов) отдельных запросов для заказов:
var query = context.Customers.Select(
c => c.Orders.Where(o => o.Amount > 100).Select(o => o.Amount));
Включив ToListAsync()
в нужное место, вы указываете, что буферизация подходит для заказов, которые позволяют оптимизировать:
var query = context.Customers.Select(
c => c.Orders.Where(o => o.Amount > 100).Select(o => o.Amount).ToList());
Обратите внимание, что этот запрос будет преобразован только в два sql-запроса: один для клиентов и следующий для заказов.
Атрибут [собственный]
Теперь можно настроить типы сущностей, просто аннотируя тип с помощью [Owned]
, а затем убедившись, что сущность владельца добавлена в модель:
[Owned]
public class StreetAddress
{
public string Street { get; set; }
public string City { get; set; }
}
public class Order
{
public int Id { get; set; }
public StreetAddress ShippingAddress { get; set; }
}
Средство командной строки dotnet-ef, включенное в пакет SDK для .NET Core
Команды dotnet-ef теперь являются частью пакета SDK для .NET Core, поэтому больше не потребуется использовать DotNetCliToolReference в проекте, чтобы использовать миграции или создать шаблон dbContext из существующей базы данных.
Дополнительные сведения о включении средств для различных версий пакета SDK для .NET Core и EF Core см. в разделе
Пакет Microsoft.EntityFrameworkCore.Abstractions
Новый пакет содержит атрибуты и интерфейсы, которые можно использовать в своих проектах, чтобы задействовать функции EF Core, не создавая зависимости от EF Core в целом. Например, атрибут [Собственный] и интерфейс ILazyLoader находятся здесь.
События изменения состояния
Новые события Tracked
и StateChanged
на ChangeTracker
можно использовать для написания логики, которая реагирует на сущности, входящие в DbContext или изменяющие их состояние.
Анализатор необработанных параметров SQL
Новый анализатор кода включен в EF Core, который обнаруживает потенциально небезопасные использования необработанных SQL API, такие как FromSql
или ExecuteSqlCommand
. Например, для следующего запроса появится предупреждение, так как minAge не параметризуется:
var sql = $"SELECT * FROM People WHERE Age > {minAge}";
var query = context.People.FromSql(sql);
Совместимость поставщика баз данных
Рекомендуется использовать EF Core 2.1 с поставщиками, которые были обновлены или по крайней мере проверены на совместимость с EF Core 2.1.