C# LINQ/EF 在具有值转换的属性上抛出无效强制转换

Posted

技术标签:

【中文标题】C# LINQ/EF 在具有值转换的属性上抛出无效强制转换【英文标题】:C# LINQ/EF throwing invalid cast on property with value conversion 【发布时间】:2021-11-23 02:41:33 【问题描述】:

在我的数据库中,我有一个表对象

   public class Objects 

        [Key]
        public int ID  get; set; 

        blah blah blah

        public JCal CreationDate  get; set; 

属性CreationDate有一个Value Converter,如下:

var stdJCalConversion = new ValueConverter<JCal, double>(
    v => v.Timestamp,
    v => new JCal(v));

    modelBuilder
        .Entity<Objects>()
        .Property(e => e.CreationDate )
        .HasConversion(stdJCalConversion );

但是当我尝试运行一个简单的 where 子句时,如下所示:

fetch = await Objects.Where(c => c.CreationDate > someDouble).ToListAsync();

我收到以下异常:InvalidCastException: Invalid cast from 'System.Double' to 'x.Types.JCal'。

定义 JCal 的结构具有运算符重载,可以在 JCal 和双精度类型之间进行比较,但我怀疑 LINQ 不能像 EF 那样使用 ValueConversions。有什么办法可以让它工作,或者有什么解决方法吗?

【问题讨论】:

你能做一个静态隐式运算符吗? 在我的 JCal 结构中:public static implicit operator double(JCal jcal) =&gt; jcal.Timestamp; public static implicit operator JCal(double timestamp) =&gt; new(timestamp); 仍然得到无效的强制转换异常 EF 对用于比较的重载一无所知。所以这意味着它无法为您的查询创建 SQL。 可能有点远,但在 SQL 中你也有 computed columns ,也许这可以执行从日期到双精度的转换,然后你只需与计算值进行比较。绝对不是答案,但可能值得研究 @JochemVanHespen 不是一个完美的解决方案,但这是个好主意。我在数据库中创建了一个 _Timestamp 记录,该记录评估为常规的 Timestamp 记录(在 asp net 中是 JCal 类型)并且有效。比我更喜欢的有点笨拙,但总比没有好 【参考方案1】:

你也许可以使用一个表达式,像这样:

public static Expression<Func<Objects, bool>> IsHigherThanDouble(double someDouble)    
        
   return (objects) => objects.CreationDate.Timestamp < someDouble;

那么你可以这样做:

fetch = await Objects.Where(IsHigherThanDouble(someDouble)).ToListAsync();

【讨论】:

以上是关于C# LINQ/EF 在具有值转换的属性上抛出无效强制转换的主要内容,如果未能解决你的问题,请参考以下文章

ORA-01017: Flyway 在 Jenkins 上抛出的用户名/密码无效

OleDbCommand 在有效的命令文本上抛出异常

在wso2上抛出异常

C# 类型转换具有不同值的对象属性

jquery颜色动画间歇性地抛出无效的属性值

杰克逊映射器在三星 SM-T580 上抛出“冲突的二传手定义”