Как предотвратить переполнение NHibernate SqlDateTime при запросе базы данных без использования IUserType? - PullRequest
1 голос
/ 29 марта 2019

Можно ли предотвратить это исключение при выполнении запроса NHibernate Linq, как показано ниже:

var dateFilter = DateTime.Parse("1500-01-01");
return _session.Query<Log>().Where(l => l.Date > dateFilter).ToList();

Результат: SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.

Я бы хотел установить минимальное поддерживаемое значение даты. Я уже использую Interceptor для этого при вставке и обновлении базы данных, но я ищу решение для исправления запросов Select.

public class DataInterceptor : EmptyInterceptor
    {
        public override bool OnFlushDirty(object entity, object id, object[] currentState, object[] previousState, string[] propertyNames, IType[] types)
        {
            DateTimeMinValueToNull(currentState, types);
            return base.OnFlushDirty(entity, id, currentState, previousState, propertyNames, types);
        }

        public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, IType[] types)
        {
            DateTimeMinValueToNull(state, types);
            return base.OnSave(entity, id, state, propertyNames, types);
        }


        // Prevents the application from crashing when an object's DateTime value is lower than the SQL datetime min value
        private void DateTimeMinValueToNull(object[] state, IType[] types)
        {
            for (int i = 0; i < types.Length; i++)
            {
                if (types[i].ReturnedClass == typeof(DateTime))
                {
                    var value = (DateTime?)state[i];
                    if (value.HasValue && value.Value < (DateTime)SqlDateTime.MinValue)
                    {
                        state[i] = (DateTime)SqlDateTime.MinValue;
                    }
                }
            }
        }
    }

Ответы [ 2 ]

3 голосов
/ 29 марта 2019

без использования IUserType

Это ограничение только для того, чтобы избежать изменения отображений?

Как и в NHibernate 5.2, вы можете зарегистрировать свой пользовательский тип по умолчанию для всех DateTime properties:

//Somewhere before SessionFactory is created
TypeFactory.RegisterType(typeof(DateTime), new YourCustomDateTime(), new[] {"DateTime"});

И с этим решением вам не нужен ваш текущий Interceptor.

0 голосов
/ 31 марта 2019

Какую версию NHibernate вы используете?

В версии 5.0.0 произошли серьезные изменения в этом поведении (https://github.com/nhibernate/nhibernate-core/blob/5.1.5/releasenotes.txt):

  • Тип Date NHibernate больше не будет заменяться нулевыми значениями ниже его базового значения (которое было в 1753 году). Его базовое значение сейчас DateTime.MinValue. Его параметр конфигурации устарел.
...