【问题标题】:Entity Framework Core 3.1 - Oracle “Specified cast is not valid”Entity Framework Core 3.1 - Oracle“指定的强制转换无效”
【发布时间】:2021-03-18 12:06:13
【问题描述】:

在我的 .NET Core 3.1 应用程序中,我使用 linq 使用以下语句从视图中获取条目列表:

List<VEntries> entryList = dbContext.VEntries.Where(x => x.Timestamp.HasValue && 
                                            x.Timestamp.Value.Date == dateTimeLocal.Date && 
                                            x.Timestamp.Value.Hour == dateTimeLocal.Hour)
                                .ToList();

dateTimeLocal 在这种情况下等于在本地时间搜索条目的时间戳。

此代码在我的本地环境中运行良好,但在生产系统上它会引发以下异常:

System.InvalidCastException:指定的强制转换无效。

在 Oracle.ManagedDataAccess.Client.OracleDataReader.GetDecimal(Int32 i)
在 lambda_method(Closure , QueryContext , DbDataReader , ResultContext , Int32[] , ResultCoordinator )
在 Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable1.Enumerator.MoveNext() at System.Collections.Generic.List1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable1 源)

两个系统上的数据库视图是相同的,并且包含一个类型为 DATE 的列 Timestamp,它可以为空:

生成的模型如下所示:

public partial class VEntries
{
    public string QualityData { get; set; }
    public decimal? Value { get; set; }
    public DateTime? Timestamp { get; set; }
    public decimal? Average { get; set; }
    public decimal? Min { get; set; }
    public decimal? Max { get; set; }
}

这可能是什么问题?

【问题讨论】:

  • 您能否发布entryData 的代码以及相关实体/视图的配置?
  • @dglozano entryData 只是 dbContext.VEntries。我相应地修改了问题。

标签: c# entity-framework linq .net-core entity-framework-core


【解决方案1】:

根据您发布的错误,我认为该错误与DateTime 字段无关,而是与decimal 字段有关:

at Oracle.ManagedDataAccess.Client.OracleDataReader.GetDecimal(Int32 i)

Oracle 的 NUMBER 范围大于 C# decimal,因此它可能无法将生产数据库中读取的一个非常大的数字转换为您的应用程序。我敢打赌,在本地工作,因为在您的本地数据库中,您没有任何大的数字。

可能的解决方案:

  1. 在生产数据库中截断或舍入小数(如果可以选择的话)。
  2. 如果第一个替代方案不可行,您可以尝试在VEntries 中为您的十进制值添加一个ValueConverter,它将从double(精度较低但范围较大)转换为decimal(精度更高,范围更小),反之亦然。

我没试过,但应该是这样的:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<VEntries>()
        .Property(e => e. Value)
        .HasConversion(
            decimalValue => (double)decimalValue,
            doubleValue => (decimal)doubleValue);
       // Repeat for all decimal values
}

【讨论】:

  • 非常感谢!这正是导致生产环境错误的原因。我认为这是一个相当大的陷阱,尽管预言机数据提供者没有考虑到这一点。
  • @Chris 很高兴你设法解决了它? 是的,这很糟糕.. 但我想它可能不想默默地截断你的数字,以防它影响你的计算。顺便说一句,只是想知道,你选择了选项 1 还是 2?
  • 选项 1,因为我们可以访问生产数据库,因此可以只对视图中的小数进行四舍五入。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-27
  • 2014-07-30
  • 2012-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多