.net EF Core 8/9 中的新增功能

科技   2024-10-18 05:50   上海  


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

  • 性能优化有利于处理大量数据或在云原生环境中运行的应用程序


  • 如果你喜欢我的文章,请给我一个赞!谢谢

架构师老卢
资深软件架构师, 分享编程、软件设计经验, 教授前沿技术, 分享技术资源(每天发布电子书),每天进步一点点...
 最新文章