Ядро Entity Framework 3.1 — Oracle “Указанный приведение недопустимо”

#c# #entity-framework #linq #.net-core #entity-framework-core

Вопрос:

В моем приложении .NET Core 3.1 я использую linq для получения списка записей из представления, используя следующую инструкцию:

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

dateTimeLocal в этом случае равна метке времени для поиска записей по местному времени.

Этот код отлично работает в моей локальной среде, но в производственной системе он вызывает следующее исключение:

Система.Исключение InvalidCastException: Указанное приведение недопустимо.

в Оракуле.Управляемый процесс.Клиент.OracleDataReader.GetDecimal(Int32 i)
в lambda_method(Закрытие , QueryContext , DbDataReader , ResultContext , Int32[] , ResultCoordinator )
в Microsoft.EntityFrameworkCore.Запрос.Внутренний.Запрос 1.Enumerator.MoveNext() at System.Collections.Generic.List неисчислимого 1..ctor( 1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable источник неисчислимого 1)

Представление базы данных идентично в обеих системах и содержит столбец Timestamp типа DATE , который может быть обнулен: введите описание изображения здесь

Сгенерированная модель выглядит следующим образом:

 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; }
}
 

В чем здесь может быть проблема?

Комментарии:

1. Не могли бы вы опубликовать код entryData , а также конфигурацию для соответствующей сущности/представления?

2. @dglozano entryData-это просто DbContext. Вентри. Я соответствующим образом изменил вопрос.

Ответ №1:

Согласно ошибке, которую вы опубликовали, я считаю, что ошибка связана не с DateTime полем, а с decimal теми, которые вместо этого:

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

NUMBER Диапазон Oracle больше, чем C# decimal , поэтому, вероятно, ему не удастся преобразовать одно очень большое число, прочитанное в рабочей базе данных, в ваше приложение. Держу пари, что локально работает, потому что в вашей локальной базе данных у вас нет такого большого числа.

Возможные решения:

  1. Усеките или округлите десятичные дроби в вашей производственной базе данных (если это возможно).
  2. Если первая альтернатива невозможна, вы можете попробовать добавить a ValueConverter для ваших десятичных значений, VEntries которые преобразуются из a 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
}
 

Комментарии:

1. Большое спасибо! Это именно то, что вызвало ошибку в производственной среде. Я думаю, что это довольно ловушка, хотя поставщик данных oracle не принимает это во внимание.

2. @Крис рад, что тебе удалось решить эту проблему 😄 да, это отстой.. но я думаю, что, вероятно, я не хочу молча усекать ваши числа, если это повлияет на ваши вычисления. Кстати, просто интересно, вы выбрали вариант 1 или 2?

3. Вариант 1, потому что у нас есть доступ к производственной базе данных, и поэтому мы можем просто округлить десятичные дроби в представлении.