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) => jcal.Timestamp; public static implicit operator JCal(double timestamp) => 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 在具有值转换的属性上抛出无效强制转换的主要内容,如果未能解决你的问题,请参考以下文章