Ошибка после обновления до синтаксического анализа XML NHibernate 3.0: строка 1, символ 4000, неожиданный конец ввода - PullRequest
1 голос
/ 09 февраля 2011

У меня есть база данных sql2008 с типом столбца xml. Используя NHibernate 2.5, я не могу сохранить в этом столбце никаких проблем.

Я опустил DLL-файлы NHibernate 3.0 и вдруг у меня появляются вышеуказанные ошибки?

Мой файл сопоставления не имеет типа для этого столбца, поэтому NHibernate наверняка должен выбрать тип данных xml (я использую диалект sql 2008)?

4000 просто кажется подозрительной длиной, то есть длиной столбца varchar в sql.

Я вижу, что есть несколько статей о сопоставлении столбцов XML с использованием пользовательских типов пользователей и т. Д.

Почему это только сработало в 2.5, а теперь нет в 3.0? Мне не нужна особая обработка. Этот столбец везде используется как строка.

Ответы [ 2 ]

3 голосов
/ 07 ноября 2011

Причина, по которой это поведение изменилось с 2.x на 3.0.0, была вызвана фиксацией кода на NHibernate.Driver.SqlClientDriver, которая фактически включила некоторые из режимов включения конфигурации prepare_sql в порядке решить проблему с кэшированием планов запросов .

Свойство C # string, сопоставленное столбцу, для которого нет другого type, указанного в его сопоставлении, будет обработано как NHibernate.SqlTypes.StringSqlType и получит ограничение в 4000 символов драйвером:

С NHibernate.SqlTypes.StringSqlType:

/// <remarks>
/// This can store the length of the string that the <see cref="IDbDataParameter"/> can hold.
/// If no value is provided for the length then the <c>Driver</c> is responsible for
/// setting the properties on the <see cref="IDbDataParameter"/> correctly.
/// </remarks>

Итак, вы можете видеть, что приведенный ниже код драйвера (NHibernate.Driver.SqlClientDriver) отображает свойство string по умолчанию на длину 4000 символов.

/* SNIP */
private const int MaxAnsiStringSize = 8000;
private const int MaxBinarySize = MaxAnsiStringSize;
private const int MaxStringSize = MaxAnsiStringSize / 2;
private const int MaxBinaryBlobSize = int.MaxValue;
private const int MaxStringClobSize = MaxBinaryBlobSize / 2;

/* SNIP */
private static void SetDefaultParameterSize(IDbDataParameter dbParam, SqlType sqlType)
{
    switch (dbParam.DbType)
    {
        /* SNIP */
        case DbType.String:
        case DbType.StringFixedLength:
            dbParam.Size = IsText(dbParam, sqlType) ? MaxStringClobSize : MaxStringSize;
            break;
        /* SNIP */
        }
    }

Для конфигураций с prepare_sql, установленным на false, NH 3.0.0 теперь вводит метод SetDefaultParameterSize в игру, где он не был до

Как вы заметили, вы можете использовать встроенную поддержку NH-3.0.0 для SQL Server XML тип данных (благодаря NH-866), например:

<property name="Data" type="xml" not-null="true" />

или более явно, но эквивалентно:

<property name="Data" type="XmlDoc" not-null="true">
  <column name="DATA" sql-type="XmlSql" />
</property>

Но при использовании NHibernate.Type.XmlDocType ожидается, что тип свойства будет иметь тип C # XmlDocument - что приведет к исключению приведения.

Вы можете сделать исправление XmlDocument.InnerXml, как вы упомянули, но это много ненужного преобразования из строки в документ и обратно. Я использовал следующее отображение, чтобы сохранить свойство домена в виде строки:

<property name="Data" type="StringClob" not-null="true">
  <column name="DATA" sql-type="XmlSql" />
</property>

Использование NHibernate.Type.StringClobType вернет true для вызова IsText(dbParam, sqlType) в приведенном выше фрагменте драйвера, давая максимальную длину символа int.MaxValue / 2 - что-то вроде 2 ГБ строковых данных.

0 голосов
/ 18 февраля 2011

Я решил эту проблему, изменив тип свойства на xml в файле сопоставления.

Затем просто использовал XmlDocument, который возвращается как XmlDocument.InnerXml, чтобы получить строковое значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...