.NET Core 2.2迁移至.NET 6后EF列映射与查询改写问题求助
问题解答
1. 保持EF实体列名与数据库完全一致
EF Core数据库优先生成实体时,默认会采用驼峰命名约定,自动将数据库中的下划线命名(如Topic_Id)转换为PascalCase格式(如TopicId)。要保留数据库的原始列名,只需在Scaffold-DbContext命令中添加--use-database-names参数即可。
修改后的完整命令:
PM> Scaffold-DbContext "Server=(servername);Database=(dbname);MultipleActiveResultSets=true;User ID=usr;Password=pass" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Data/DB -force --use-database-names
该参数会强制EF Core直接复用数据库中的表名、列名,不执行任何命名转换。
2. 避免将查询转换为IEnumerable,优化.NET 6查询代码
你完全不需要将查询转换为IEnumerable——这种写法会把整张表的数据加载到内存后再过滤,严重损耗性能。当前问题源于对EF Core 3.0+查询翻译规则的变化不熟悉,以下是正确的优化方案:
问题根源
- .NET Core 2.2的EF Core对空值处理较宽松,允许直接调用
null对象的方法(如Code.ToLower());但EF Core 3.0+开始严格执行查询翻译,不支持无法转换为SQL的空引用操作。 - 原代码未显式
Include关联导航属性,可能依赖了.NET Core 2.2默认开启的延迟加载;而.NET 6默认关闭了延迟加载,因此需要显式Include或重新开启延迟加载。
正确的.NET 6查询写法(保持IQueryable,数据库端执行)
db.TblUserCredential? UserCredential = this.DbContext.TblUserCredentials .Include(x => x.CredentialTypeNavigation) // 显式加载关联属性,开启延迟加载后可省略 .Where(x => x.CredentialTypeNavigation.Code != null && EF.Functions.Like(x.CredentialTypeNavigation.Code.ToLower(), "%kingsid%")) .FirstOrDefault(x => x.Identifier != null && x.Identifier.Equals(identifier, StringComparison.OrdinalIgnoreCase));
额外优化建议
- 开启延迟加载:若希望和.NET Core 2.2一样自动加载关联属性,可在DbContext的
OnConfiguring方法中添加:
开启后可去掉optionsBuilder.UseLazyLoadingProxies();Include语句,但需注意延迟加载可能引发N+1查询问题,需根据业务场景选择。 - 使用EF.Functions:
EF.Functions.Like会被翻译为SQL的LIKE语句,比内存中执行Contains性能更优;若需忽略大小写,也可直接在SQL层面处理(如LOWER(Code) LIKE '%kingsid%')。 - 空值检查:EF Core 3.0+要求必须显式处理可能为null的属性,避免查询中出现潜在的空引用异常。
内容的提问来源于stack exchange,提问作者M G
相关产品推荐
相关产品推荐

