EF 6迁移至EF Core 7:Guid.ToString()生成SQL大小写差异解决问询
EF Core 7 替换 Guid.ToString() 生成小写 GUID 查询方案
方案1:自定义扩展方法+数据库函数映射
适合愿意修改少量代码的场景,直观易维护。
1. 编写Guid扩展方法
创建静态类实现客户端的小写转换逻辑:
public static class GuidExtensions { // 非可空Guid转小写字符串 public static string ToLowerString(this Guid guid) => guid.ToString("D").ToLower(); // 可空Guid转小写字符串 public static string? ToLowerString(this Guid? guid) => guid?.ToString("D").ToLower(); }
2. 在DbContext中注册函数映射
在OnModelCreating里配置EF Core如何将扩展方法翻译为SQL:
protected override void OnModelCreating(ModelBuilder modelBuilder) { // 映射非可空Guid的ToLowerString modelBuilder.HasDbFunction(() => GuidExtensions.ToLowerString(default(Guid))) .HasTranslation(parameters => EF.Functions.Lower(EF.Functions.ToString(parameters.First(), "D"))); // 映射可空Guid的ToLowerString modelBuilder.HasDbFunction(() => GuidExtensions.ToLowerString(default(Guid?))) .HasTranslation(parameters => { var guidParam = parameters.First(); return Expression.Condition( Expression.NotEqual(guidParam, Expression.Constant(null, typeof(Guid?))), EF.Functions.Lower(EF.Functions.ToString(Expression.Property(guidParam, "Value"), "D")), Expression.Constant(null, typeof(string)) ); }); }
之后将项目中所有Guid.ToString()/Guid?.ToString()替换为ToLowerString()即可,生成的SQL会自动生成LOWER(CONVERT(NVARCHAR(36), [Column])),得到小写GUID。
方案2:全局表达式树替换(无需修改原有代码)
适合大规模项目,自动替换所有ToString()调用,无需改动业务代码。
1. 编写表达式访问器
用于识别并替换表达式树中的Guid.ToString()节点:
public class GuidToStringRewriter : ExpressionVisitor { protected override Expression VisitMethodCall(MethodCallExpression node) { // 匹配无参数的Guid.ToString()或Guid?.ToString()调用 if ((node.Method.DeclaringType == typeof(Guid) || node.Method.DeclaringType == typeof(Guid?)) && node.Method.Name == nameof(ToString) && node.Arguments.Count == 0) { // 获取对应的ToLowerString方法 var targetMethod = typeof(GuidExtensions).GetMethod( nameof(GuidExtensions.ToLowerString), new[] { node.Object.Type })!; // 替换为扩展方法调用 return Expression.Call(targetMethod, node.Object); } return base.VisitMethodCall(node); } }
2. 注册查询拦截器
让EF Core在编译查询前自动替换表达式:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { // 添加查询拦截器 optionsBuilder.AddInterceptors(new GuidToStringInterceptor()); } public class GuidToStringInterceptor : IQueryExpressionInterceptor { public Expression QueryCompilationStarting(Expression queryExpression, QueryExpressionEventData eventData) { // 重写查询表达式 return new GuidToStringRewriter().Visit(queryExpression); } }
完成配置后,项目中所有原有Guid.ToString()/Guid?.ToString()的查询都会被自动转换为小写GUID的SQL,完全无需修改业务代码。
注意事项
- 两种方案都适配Azure SQL Server,生成的SQL与EF6的行为完全一致;
- 方案1代码侵入性低,适合小范围调整;方案2无代码侵入,适合大规模迁移场景。
内容的提问来源于stack exchange,提问作者Han Moe Htet
相关产品推荐
相关产品推荐

