首页
/ EF Core 9.0 中关于只读集合属性的迁移问题解析

EF Core 9.0 中关于只读集合属性的迁移问题解析

2025-05-16 08:22:10作者:牧宁李

在 EF Core 9.0 版本中,开发者在使用只读集合属性时遇到了一个特殊的迁移问题。这个问题表现为:当模型类中包含一个带有私有后备字段的 IReadOnlyCollection<string> 属性时,虽然数据库的创建和删除操作能够正常执行,但在尝试添加新的迁移时却会抛出异常。

问题现象

典型的错误场景如下:开发者在模型类中定义了一个只读集合属性,并为其配置了私有后备字段:

public class Model
{
    public int Id { get; set; }
    public IReadOnlyCollection<string> Uids => _uids.ToList();
    private List<string> _uids = [];
}

在 DbContext 中,开发者可能这样配置:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Model>().Property(x => x.Uids).HasField("_uids");
}

当执行 dotnet ef migrations add 命令时,系统会抛出以下异常:

System.InvalidOperationException: Cannot scaffold C# literals of type 'System.Reflection.NullabilityInfoContext'. The provider should implement CoreTypeMapping.GenerateCodeLiteral to support using it at design time.

问题根源

这个问题的根本原因在于 EF Core 9.0 中对集合属性的处理方式发生了变化。开发者使用了 Property() 方法来配置集合属性,而实际上对于原始类型集合(如字符串集合),应该使用 PrimitiveCollection() 方法。

EF Core 团队确认这是一个框架层面的问题,特别是在设计时(design-time)处理 NullabilityInfoContext 类型时出现了异常。这个问题不仅出现在 SQL Server 提供程序中,其他数据库提供程序(如 PostgreSQL)也报告了相同的问题。

解决方案

临时解决方案

在 EF Core 9.0.2 修复发布前,开发者可以采用以下两种临时解决方案:

  1. 使用 PrimitiveCollection 替代 Property
modelBuilder.Entity<Model>().PrimitiveCollection(x => x.Uids).HasField("_uids");
  1. 使用自定义值转换器
modelBuilder.Entity<Model>().Property(x => x.Uids)
    .HasField("_uids")
    .HasConversion(
        v => JsonConvert.SerializeObject(v),
        v => JsonConvert.DeserializeObject<List<string>>(v)!,
        ReadOnlyCollectionValueComparer<string>.Create());

官方修复

EF Core 团队已经确认将在 9.0.2 版本中修复这个问题。修复预计在 2024 年 2 月中旬发布。

最佳实践建议

  1. 集合属性配置:对于原始类型集合(如字符串、整数等),始终使用 PrimitiveCollection() 方法进行配置。

  2. 只读集合模式:虽然只读集合模式(通过返回 ToList() 的副本来保护内部集合)是一种良好的实践,但在 EF Core 中需要特别注意配置方式。

  3. 版本选择:如果项目依赖此功能,建议等待 9.0.2 版本发布后再升级,或者采用上述临时解决方案。

总结

这个问题展示了 EF Core 在处理复杂类型和设计时代码生成时的内部机制。开发者在使用只读集合属性时需要特别注意配置方法,避免使用不支持的 API 组合。EF Core 团队已经确认了这个问题并将很快发布修复,在此期间开发者可以选择使用 PrimitiveCollection 或自定义转换器作为临时解决方案。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
leetcodeleetcode
🔥LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解
Java
51
14
RuoYi-Vue3RuoYi-Vue3
🎉 (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统
Vue
445
365
ohos_react_nativeohos_react_native
React Native鸿蒙化仓库
C++
97
177
openGauss-serveropenGauss-server
openGauss kernel ~ openGauss is an open source relational database management system
C++
52
120
MateChatMateChat
前端智能化场景解决方案UI库,轻松构建你的AI应用,我们将持续完善更新,欢迎你的使用与建议。 官网地址:https://matechat.gitcode.com
637
77
openHiTLSopenHiTLS
旨在打造算法先进、性能卓越、高效敏捷、安全可靠的密码套件,通过轻量级、可剪裁的软件技术架构满足各行业不同场景的多样化要求,让密码技术应用更简单,同时探索后量子等先进算法创新实践,构建密码前沿技术底座!
C
88
245
CangjieMagicCangjieMagic
基于仓颉编程语言构建的 LLM Agent 开发框架,其主要特点包括:Agent DSL、支持 MCP 协议,支持模块化调用,支持任务智能规划。
Cangjie
562
39
arkanalyzerarkanalyzer
方舟分析器:面向ArkTS语言的静态程序分析框架
TypeScript
29
36
Cangjie-ExamplesCangjie-Examples
本仓将收集和展示高质量的仓颉示例代码,欢迎大家投稿,让全世界看到您的妙趣设计,也让更多人通过您的编码理解和喜爱仓颉语言。
Cangjie
274
470
open-eBackupopen-eBackup
open-eBackup是一款开源备份软件,采用集群高扩展架构,通过应用备份通用框架、并行备份等技术,为主流数据库、虚拟化、文件系统、大数据等应用提供E2E的数据备份、恢复等能力,帮助用户实现关键数据高效保护。
HTML
109
73