EF Core中在Where子句比较ComplexType的问题求助
最优解决方案
1. 修复MSISDN类的基础问题
- 自定义
ToString()未重写基类方法,需添加override关键字,否则调用的是默认object.ToString():public override string ToString() => $"{NDC}{SN}{CC}"; ToLong()存在语法错误,字符串无法直接与数值运算,修正为:public string ToLong() { long ndc = long.Parse(NDC); long sn = long.Parse(SN); long cc = long.Parse(CC); return (ndc * (long)Math.Pow(10, 6) + sn * (long)Math.Pow(10, 3) + cc).ToString(); }
2. 确保ValueConverter正确注册到EF Core模型
在DbContext的OnModelCreating方法中,为SubscriberCard.Msisdn属性配置转换器与数据库类型:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<SubscriberCard>() .Property(s => s.Msisdn) .HasConversion(new MsisdnValueConverter()) .HasColumnType("NVARCHAR(MAX)"); // 显式指定类型,避免EF自动推断错误 }
3. 直接使用实体属性比较
注册正确的转换器后,EF Core会自动处理复杂类型与数据库字符串的双向转换,直接使用原始比较逻辑即可,无需额外调用ToString():
SubscriberCard card = cardDbSet.FirstOrDefault(p => p.Msisdn == msisdn);
第一个异常的根源是转换器未正确注册,导致EF错误地将数据库字符串映射为数值类型,完成注册后即可解决类型转换问题。
4. 自定义字符串比较的替代方案
如果需要直接匹配数据库中的字符串格式,可通过EF.Property直接访问数据库字段,绕开客户端转换:
string targetMsisdnStr = msisdn.ToString(); SubscriberCard card = cardDbSet.FirstOrDefault(p => EF.Property<string>(p, "Msisdn") == targetMsisdnStr);
此方法让EF生成原生SQL字符串比较逻辑,性能与直接属性比较一致。
为何不优先选择DbFunction?
DbFunction需要额外配置数据库函数映射,开发与维护成本更高。上述方案通过修复转换器注册、利用EF原生特性,即可在数据库层面完成过滤,性能与代码简洁性均优于自定义DbFunction。
内容的提问来源于stack exchange,提问作者RezaNoei
相关产品推荐
相关产品推荐

