升级到NHibernate 3.0 XML解析后出错:第1行,第4000行,意外的输入结束

时间:2011-02-09 16:11:54

标签: nhibernate

我有一个sql2008 db,其列类型为xml。 使用NHibernate 2.5我可以保存到这个列没有问题。

我已经退出了NHibernate 3.0 dll,突然间我遇到了上述错误?

我的映射文件没有针对该列的类型,所以NHibernate肯定会选择xml数据类型(我使用的是sql 2008方言)?

4000似乎是一个可疑的长度,即sql中varchar列的长度。

我看到有一些关于使用自定义UserTypes等映射xml列的文章。

为什么这只是在2.5中工作而现在不在3.0中?我不需要任何特殊处理。该列在任何地方都被用作字符串。

2 个答案:

答案 0 :(得分:3)

此行为从2.x更改为3.0.0的原因归因于NHibernate.Driver.SqlClientDriver上的a code commit,这有效地启用了按顺序启用prepare_sql配置的一些行为解决issue with the caching of query plans

映射到其映射中未指定其他string的列的AC#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方法置于其中之前的位置

如您所述,您可以对SQL Server XML数据类型使用NH-3.0.0本机支持(感谢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将在上面的驱动程序代码段中为IsText(dbParam, sqlType)调用返回true,最大字符长度为int.MaxValue / 2 - 类似于2GB的字符串数据。

答案 1 :(得分:0)

我通过在映射文件中将属性类型更改为xml来解决此问题。

然后只使用作为XmlDocument.InnerXml返回的XmlDocument来获取字符串值。