Entity Framework Core (EF Core) 不断发展以满足现代软件开发的需求,EF Core 8/9(也称为 EF8/9)的发布延续了这一传统,提供了一系列功能,这些功能可提高性能、简化数据操作并为开发人员扩展灵活性。本文将探讨 EF Core 8/9 中的关键更新,并提供有关如何在实际场景中使用它们的实用见解。
1. 引言
EF Core 8/9 是更广泛的 .NET 8/9 生态系统的一部分,旨在优化性能和开发人员工作效率。EF Core 8/9 非常注重云原生、高性能的应用程序,为批量操作、JSON 支持、查询改进和简化的架构处理带来了增强功能。此外,开发人员在从以前的版本迁移时,还需要注意许多重大更改。
主要亮点:
增强了批量操作的性能。
关系数据库中的原生 JSON 支持。
针对复杂查询的优化 LINQ 功能。
在 SQL Server 中支持 HierarchyId。
改进了延迟加载和更改跟踪。
支持未映射类型的原始 SQL 查询。
改进了 Schema 迁移处理。
让我们深入了解这些新功能并探索它们的实际应用。
2. JSON 列支持
JSON 数据越来越多地用于现代应用程序,EF Core 8/9 加深了对关系数据库中 JSON 列的支持。这包括更高效地查询、映射和操作 JSON 数据的能力,尤其是对于 PostgreSQL 和 SQL Server 等数据库。
新增功能
JSON 中的基元集合:您现在可以在 JSON 列内映射和查询基元类型的集合,从而提高处理半结构化数据时的灵活性。
增强的查询功能:EF Core 8/9 允许在 JSON 数据中进行更复杂的查询,例如根据 JSON 中存储的属性筛选数据。
例:
想象一下,您将用户首选项存储在 JSON 列中。在以前的版本中,查询 JSON 列中的特定字段需要原始 SQL 或将整个 JSON 对象加载到内存中。EF Core 8/9 允许您直接使用 LINQ 定位这些字段。
var usersWithEmailNotifications = dbContext.Users
.Where(u => u.Preferences.EmailNotificationsEnabled == true)
.ToList();
在此示例中,查询仅提取其首选项包括启用电子邮件通知的用户,而不加载整个 JSON 负载。这种改进的查询效率在处理大型数据集时节省了时间和资源。
此外,SQLite 现在支持具有增强功能的 JSON 列,从而可以更轻松地管理和查询较小的嵌入式数据库的 JSON 数据。
3. 批量操作以获得更好的性能
有效处理大型数据集一直是 ORM 框架的一个挑战。EF Core 8/9 允许更高效地执行批量插入、更新和删除操作,减少数据库往返次数并提高性能,尤其是在云环境中,从而显著改进了批量操作。
批量更新示例:
在以前的版本中,开发人员必须遍历实体才能单独更新它们,从而导致性能瓶颈。EF Core 8/9 引入了优化的批量操作,可在更少的数据库调用中处理更新。
await dbContext.Users
.Where(u => u.IsArchived)
.ExecuteUpdateAsync(user =>
user.SetProperty(u => u.LastLogin, DateTime.UtcNow));
此方法允许您在单个操作中更新多个记录,从而大大提高存档旧用户记录或标记非活动数据等任务的性能。
关键要点:
更快地处理大型数据集。
减少数据库调用,减少高流量环境中的延迟。
非常适合批处理,非常适合 ETL 流程等数据密集型应用程序。
4. LINQ 查询增强功能
EF Core 8/9 为语言集成查询 (LINQ) 引入了许多增强功能,为开发人员提供了更具表现力和更高效的数据库交互方式。在处理复杂查询或大型数据集时,这些改进尤其相关。
新功能:
通过聚合增强功能:您现在可以直接在数据库中执行更复杂的查询,而不是将所有数据提取到内存中并在客户端执行操作。GroupByGroupBy
支持使用 SQL Server 临时表进行时间旅行查询:EF Core 8/9 支持历史数据查询,允许开发人员从特定时间点检索数据。
with Aggregates 的示例:GroupBy
以前,使用聚合函数执行操作通常需要客户端处理,这会影响性能。现在,这些操作可以直接在数据库中运行,从而提高速度和资源利用率。GroupBy
var monthlyOrders = dbContext.Orders
.GroupBy(o => new { o.CustomerId, Month = o.Date.Month })
.Select(g => new
{
CustomerId = g.Key.CustomerId,
Month = g.Key.Month,
TotalAmount = g.Sum(o => o.TotalAmount)
}).ToList();
此查询允许您按客户和月份对订单进行分组,计算对应用程序性能影响最小的总金额。
5. 原始 SQL 查询改进
EF Core 8/9 进一步增强了原始 SQL 查询支持,使原始 SQL 命令与 EF 的更改跟踪机制之间能够更好地集成。您现在可以对未映射的类型执行原始 SQL 查询,从而在与未直接映射到 EF 实体的数据交互时提供更大的灵活性。
例:
想象一下这样一种情况:您需要执行一个没有整齐映射到实体的复杂查询,例如存储过程或涉及具有自定义联接的多个表的查询。
var inactiveUsers = await dbContext.Users
.FromSqlRaw("SELECT * FROM Users WHERE IsInactive = 1")
.ToListAsync();
在此示例中,您可以使用原始 SQL 检索数据,同时仍受益于 EF Core 的跟踪和延迟加载功能,使原始 SQL 对性能关键型操作更有用。
6. SQL Server 中的 HierarchyId 支持
EF Core 8/9 中的另一个显著改进是 SQL Server 中对 的官方支持。数据类型有助于以更高效的方式表示分层数据,例如组织结构或目录树。HierarchyIdHierarchyId
此功能简化了分层数据的查询和操作,以前需要自定义解决方法或原始 SQL 来管理。
7. 实用的数据库模式处理
在具有多个开发人员的大型应用程序中,管理数据库架构更改可能很棘手。EF Core 8/9 通过更好地处理常见操作(如列重命名和冲突解决)来改进架构迁移体验。
例:
在数据库架构定期演变的 CI/CD 环境中,EF Core 8 现在以减少部署期间潜在的数据丢失或错误的方式处理迁移。重命名列不再触发完整数据重新创建,从而最大程度地降低架构更新期间的风险。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>().Property(o => o.TotalAmount)
.HasColumnName("OrderTotal"); // Renaming columns intelligently
}
在定期更新和部署架构更改的团队中工作时,此功能特别有用。
8. 性能和可扩展性增强
EF Core 8/9 提供了多项后台性能优化:
更快的查询执行速度:缩短了查询编译时间,从而减少了复杂查询的延迟。
优化的连接池:更高效地使用数据库连接有助于基于云的应用程序,在这些应用程序中,连接可能会成为瓶颈。
更好的延迟加载和更改跟踪:这些改进减少了与加载相关数据相关的开销,尤其是在处理大型模型时。
例:
严重依赖相关实体(如电子商务平台)延迟加载的应用程序会注意到 EF Core 8/9 的性能有了显著提高。
9. 需要注意的重大更改
虽然 EF Core 8/9 带来了广泛的增强功能,但开发人员还必须注意此版本中引入的几项重大更改。这些更改可能会影响从较旧的 EF Core 版本升级的应用程序,并且可能需要调整代码以确保兼容性。
关键重大变化:
布尔列:在以前的 EF Core 版本中,具有默认值的列被搭建为可为 null 的属性 ()。EF Core 8/9 不再将这些列设置为可为 null,这可能会影响数据库优先工作流,尤其是在数据库架构对列使用默认约束时。boolbool?bool
缓解措施:如果您无法轻松重构代码,则需要修改代码以使用不可为 null 的属性或调整基架模板。这可以通过更新基架模板中的文件来处理这些更改来完成。boolEntityType.t4
使用 and 类型搭建基架:EF Core 8/9 为 和 引入了新类型,这将替换数据库优先工作流中的旧映射。此更改会影响定期重新搭建数据库模型的开发人员。DateOnlyTimeOnlyDateOnlyTimeOnlyDateTime
缓解措施:如有必要,您可以编辑基架模板以恢复到以前的映射。但是,建议尽可能采用 new and 类型,以便面向未来。DateOnlyTimeOnly
SQLite 数学函数:EF Core 8/9 增强了对 SQLite 数学方法(如 、 和 )的支持,这些方法现在可直接转换为 SQL。这样就无需对这些方法进行客户端评估,但是使用没有这些函数的自定义 SQLite 库的开发人员可能会遇到错误。Math.PowMath.SinMath.Cos
缓解措施:如果您的 SQLite 库不支持这些函数,请考虑切换到默认的 SQLite 提供程序或使用 .Microsoft.Data.Sqlite
API 中的更改:随着 EF Core 8/9 中复杂类型的引入,以前使用的一些 API 现在使用 .这些更改旨在通用化实体类型和复杂类型的 API 用法,但它们可能需要重构代码以更新对过时 API 的调用,例如IEntityTypeIEntityTypeITypeBaseIProperty.DeclaringEntityType.
布尔列更改的实际示例:
在早期版本的 EF Core 中,由于默认约束,可能会从不可为 null 的数据库列搭建属性。但是,EF Core 8/9 现在将其正确地设置为 ,更准确地反映实际的数据库架构。bool?bool
// Old behavior
public bool? IsActive { get; set; } // Previously scaffolded with nullable type
// New behavior in EF Core 8/9
public bool IsActive { get; set; } // Non-nullable, better aligned with database schema
这些重大变化反映了 EF Core 8/9 向更好的架构处理和更紧密地与实际数据库设计保持一致的转变,从而减少了开发人员的歧义。
10. 性能和可扩展性增强
EF Core 8/9 非常注重提高性能和可扩展性,使其非常适合高需求的云原生应用程序。改进的关键领域包括更快的查询执行、增强的连接池以及更好地处理延迟加载的数据。
优化的查询执行:
EF Core 8/9 优化了查询编译和执行,从而减少了复杂查询的延迟。这些改进在执行大量动态查询或严重依赖 LINQ 进行业务逻辑的应用程序中尤为明显。
延迟加载改进:
延迟加载(一种将相关数据的加载推迟到显式访问的功能)也在 EF Core 8/9 中进行了优化。这使得框架在处理大型模型和复杂关系时更加高效。
连接池:
EF Core 8/9 还引入了更高效的连接池,可以更轻松地在高并发环境(如云原生和微服务架构)中管理数据库连接。这对于数据库连接因高流量而成为瓶颈的情况至关重要。
优化查询执行示例:
在电子商务应用程序中,您可能有这样一个场景:您需要根据各种属性(如价格、类别和库存可用性)动态筛选产品。在以前的版本中,动态生成的查询的开销可能会导致性能问题。借助 EF Core 8/9 改进的查询编译,即使是复杂的筛选器也可以高效运行。
var products = dbContext.Products
.Where(p => p.Price < 100 && p.InStock)
.OrderBy(p => p.Name)
.ToList();
EF Core 8/9 可以更高效地处理此问题,从而减少编译和执行查询的时间,尤其是在处理大型数据集时。
EF Core 8/9 带来了大量新功能和改进,可简化开发,特别是对于高性能和基于云的应用程序。包含 JSON 支持、批量操作、增强的 LINQ 查询和优化的架构迁移使开发人员能够更轻松地使用它。
主要优点:
JSON 支持允许在混合 NoSQL 关系场景中实现更灵活、更高效的数据管理。
批量操作可以提高批处理作业和数据处理管道的性能。
LINQ 增强功能使编写富有表现力、功能强大的查询变得更加容易,而不会牺牲性能。
布尔处理、/ 类型和基架方面的重大变化需要开发人员进行调整,但它们有助于使模型与实际数据库架构更紧密地保持一致。DateOnlyTimeOnly
性能优化有利于处理大量数据或在云原生环境中运行的应用程序
点击下方卡片关注DotNet NB
一起交流学习
▲ 点击上方卡片关注DotNet NB,一起交流学习
请在公众号后台