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