我有一个sql2008 db,其列类型为xml。 使用NHibernate 2.5我可以保存到这个列没有问题。
我已经退出了NHibernate 3.0 dll,突然间我遇到了上述错误?
我的映射文件没有针对该列的类型,所以NHibernate肯定会选择xml数据类型(我使用的是sql 2008方言)?
4000似乎是一个可疑的长度,即sql中varchar列的长度。
我看到有一些关于使用自定义UserTypes等映射xml列的文章。
为什么这只是在2.5中工作而现在不在3.0中?我不需要任何特殊处理。该列在任何地方都被用作字符串。
答案 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来获取字符串值。