NHibernate не сохранит переполнение DateTime SqlDateTime

Я работаю над проектом ASP.NET MVC с NHibernate в качестве бэкэнда, и у меня возникают проблемы с получением некоторых дат для записи обратно в таблицы базы данных SQL Server.

Эти поля даты НЕ допускают значения NULL, поэтому многие ответы здесь о том, как настроить дату, допускающую значение NULL, не помогли.

Обычно, когда я пытаюсь сохранить объект с полями DateAdded и LastUpdated, я получаю исключение переполнения SqlDateTime. У меня была аналогичная проблема в прошлом, когда я пытался записать поле datetime в столбец smalldatetime, обновив тип в столбце, чтобы решить проблему. Мне кажется, что это будет некоторая проблема с определением таблицы или несовместимыми типами данных, а исключение переполнения - это что-то вроде бездельника.

Я приложил пример определения таблицы и запроса, который пытается выполнить NHibernate, любая помощь или предложения будут очень благодарны.

CREATE TABLE [dbo].[CustomPages](
    [ID] [uniqueidentifier] NOT NULL,
    [StoreID] [uniqueidentifier] NOT NULL,
    [DateAdded] [datetime] NOT NULL,
    [AddedByID] [uniqueidentifier] NOT NULL,
    [LastUpdated] [datetime] NOT NULL,
    [LastUpdatedByID] [uniqueidentifier] NOT NULL,
    [Title] [nvarchar](150) NOT NULL,
    [Term] [nvarchar](150) NOT NULL,
    [Content] [ntext] NULL
)

exec sp_executesql N'INSERT INTO CustomPages (Title, Term, Content, LastUpdated, DateAdded, StoreID, LastUpdatedById, AddedById, ID) VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8)',N'@p0 
nvarchar(21),@p1 nvarchar(21),@p2 nvarchar(33),@p3 datetime,@p4 datetime,@p5 uniqueidentifier,@p6 uniqueidentifier,@p7 uniqueidentifier,@p8 uniqueidentifier',@p0=N'Size and Colour 
Chart',@p1=N'size-and-colour-chart',@p2=N'This is the size and colour chart',@p3=''2009-03-14 14:29:37:000'',@p4=''2009-03-14 
14:29:37:000'',@p5='48315F9F-0E00-4654-A2C0-62FB466E529D',@p6='1480221A-605A-4D72-B0E5-E1FE72C5D43C',@p7='1480221A-605A-4D72-B0E5-E1FE72C5D43C',@p8='1E421F9E-9A00-49CF-9180-DCD22FCE7F55'

В ответ на ответы / комментарии я использую Fluent NHibernate, и сгенерированное сопоставление приведено ниже.

  public CustomPageMap() {

            WithTable("CustomPages");

            Id( x => x.ID, "ID" )
                .WithUnsavedValue(Guid.Empty)
            .   GeneratedBy.Guid();

            References(x => x.Store, "StoreID");

            Map(x => x.DateAdded, "DateAdded");
            References(x => x.AddedBy, "AddedById");
            Map(x => x.LastUpdated, "LastUpdated");
            References(x => x.LastUpdatedBy, "LastUpdatedById");


            Map(x => x.Title, "Title");
            Map(x => x.Term, "Term");
            Map(x => x.Content, "Content");

        }  

    <?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false" assembly="MyNamespace.Core" namespace="MyNamespace.Core">
<class name="CustomPage" table="CustomPages" xmlns="urn:nhibernate-mapping-2.2">
<id name="ID" column="ID" type="Guid" unsaved-value="00000000-0000-0000-0000-000000000000"><generator class="guid" /></id>
<property name="Title" column="Title" length="100" type="String"><column name="Title" /></property>
<property name="Term" column="Term" length="100" type="String"><column name="Term" /></property>
<property name="Content" column="Content" length="100" type="String"><column name="Content" /></property>
<property name="LastUpdated" column="LastUpdated" type="DateTime"><column name="LastUpdated" /></property>
<property name="DateAdded" column="DateAdded" type="DateTime"><column name="DateAdded" /></property>
<many-to-one name="Store" column="StoreID" /><many-to-one name="LastUpdatedBy" column="LastUpdatedById" />
<many-to-one name="AddedBy" column="AddedById" /></class></hibernate-mapping>

person chris raethke    schedule 14.03.2009    source источник
comment
Ваша таблица и SQL кажутся нормальными. Работает ли этот SQL-запрос, если вы попробуете запустить его вручную? Возможно, стоит разместить здесь код и файл сопоставления гибернации.   -  person Andy White    schedule 14.03.2009
comment
Да, запрос работает нормально в анализаторе запросов SQL, за исключением того, что мне нужно заменить двойные одинарные кавычки вокруг даты и времени (как строки стиля utc) на одинарные кавычки, этот запрос генерируется nhibernate   -  person chris raethke    schedule 14.03.2009


Ответы (6)


На самом деле причина за кулисами:

Когда NHibernate читает строку из базы данных, значение равно нулю, и это то, что запоминает сеанс. Когда объект повторно гидратируется NHibernate, Date устанавливается в значение DateTime.MinValue. Когда сеанс синхронизируется с базой данных, NHibernate предполагает, что что-то изменилось, потому что currentState и previousState разные, и пытается обновить строку. Что, в свою очередь, не работает, потому что DateTime.MinValue не помещается в столбец datetime SqlServer.

Решение: сделайте дату и время нулевой, поставив? в конце Datetime, например DateTime? или Nullable

полную статью можно найти по адресу: nhibernate-sqldatetime-overflow-issue

person Zafar    schedule 27.07.2009

Я столкнулся с той же таблицей проблем с столбцами datetime, не допускающими значения NULL, и переполнением SqlDateTime при сохранении.

В моем случае реальная проблема заключалась в том, что при сохранении запускался session.flush, который вызывает обновление некоторого объекта, загруженного ранее с использованием того же сеанса. У этого объекта была проблема «поля даты и времени, в которых должно было использоваться поле даты и времени, допускающее значение NULL».

Другими словами: попробуйте выполнить session.flush перед сохранением или обновлением, чтобы проверить, не вызвана ли проблема более ранним использованием того же объекта сеанса.

Надеюсь, что это кому-нибудь поможет.

person Ivo Grootjes    schedule 21.09.2011

Почему @ p3 и @ p4 имеют двойные одинарные кавычки? Ошибка копирования и вставки?

Я не могу проверить (здесь не установлен SQL), но должен ли разделитель миллисекунд не должен быть "точкой", то есть "2009-03-14 14: 29: 37.000"

@ p3 - "до", @ p4 - "после" здесь:

exec sp_executesql
  N'INSERT INTO CustomPages (Title, Term, Content, LastUpdated, DateAdded, StoreID, LastUpdatedById, AddedById, ID)
  VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8)',
  N'@p0 nvarchar(21),@p1 nvarchar(21),@p2 nvarchar(33),@p3 datetime,@p4 datetime,@p5 uniqueidentifier,@p6 uniqueidentifier,@p7 uniqueidentifier,@p8 uniqueidentifier',

    @p0=N'Size and Colour Chart',
    @p1=N'size-and-colour-chart',
    @p2=N'This is the size and colour chart',
    @p3=''2009-03-14 14:29:37:000'', --quotes + dot wrong?
    @p4='2009-03-14 14:29:37.000', --quotes + dot correct?
    @p5='48315F9F-0E00-4654-A2C0-62FB466E529D',
    @p6='1480221A-605A-4D72-B0E5-E1FE72C5D43C',
    @p7='1480221A-605A-4D72-B0E5-E1FE72C5D43C',
    @p8='1E421F9E-9A00-49CF-9180-DCD22FCE7F55'
person gbn    schedule 14.03.2009
comment
Да, я подумал, что способ отображения дат тоже был немного странным, однако он работает в анализаторе запросов, за исключением того, что мне нужно поменять двойные кавычки на одинарные. Я просмотрел главу 5 nhibernate doco, думая, что могу сказать nhibernate, как исправить диалект, но это действительно выглядит возможным - person chris raethke; 14.03.2009
comment
Формат 14: 29: 37: 000 2009-03-14 неверен для SQL Server. - person gbn; 15.03.2009
comment
Диалект может быть вашей проблемой. Почему вы говорите, что это невозможно установить? Как вы создаете свой SessionFactory? Вы читаете его из файла конфигурации или создаете программно? - person Andy White; 15.03.2009

Сценарий SQL в вашем вопросе отлично выполнил мою установку SQL 2005 (как только я исправил проблемы с цитатой, поднятые gbn). И ваше отображение тоже выглядит нормально. Извините, что так мало помог.

person John Rayner    schedule 16.03.2009

Я использовал s # architecture / fluentnhibernate для создания этого сопоставления, я обновился до последней версии, и, похоже, все работает нормально.

person chris raethke    schedule 19.04.2009

К вашему сведению, я работал над переносом существующего приложения на NHibernate из различных встроенных подходов к доступу к данным. Эта проблема возникла быстро, и я нашел простое решение, которое минимизировало влияние на существующий функциональный код приложения. Поскольку в некоторых случаях мы осуществляем поэтапную миграцию, интерфейс класса данных должен был оставаться стабильным, если это вообще возможно. Решением здесь было продолжить использование типов DateTime для общедоступного интерфейса, добавить методы расширения к типам закрытых полей для преобразования из MinValue в null и обратно в закрытые поля в средствах доступа и сопоставить nHibernate с частными полями.

JF

person user324534    schedule 23.04.2010