Проблема усечения NHibernate nvarchar/ntext
Я использую nhibernate для хранения некоторых пользовательских настроек приложения в таблице SQL Server Compact Edition.
Это выдержка из файла сопоставления:
<property name="Name" type="string" />
<property name="Value" type="string" />
Имя - это обычная строка /nvarchar(50), а в качестве значения в БД задано значение ntext.
Я пытаюсь написать большое количество XML для свойства "Значение". Я получаю исключение каждый раз:
@p1 : String truncation: max=4000, len=35287, value='<lots of xml..../>'
Я немного погуглил и попробовал несколько разных конфигураций сопоставления:
<property name="Name" type="string" />
<property name="Value" type="string" >
<column name="Value" sql-type="StringClob" />
</property>
Это один пример. Другие конфигурации включают "ntext" вместо "StringClob". Те конфигурации, которые не генерируют исключения сопоставления, по-прежнему генерируют исключение усечения строки.
Это проблема ("особенность") с SQL CE? Можно ли поместить более 4000 символов в базу данных SQL CE с помощью nhibernate? Если так, может кто-нибудь сказать мне, как?
Большое спасибо!
7 ответов
Хорошо, с огромной благодарностью Артура в этом потоке, вот решение: Наследуйте от SqlServerCeDriver с новым, и переопределите метод InitializeParamter:
using System.Data;
using System.Data.SqlServerCe;
using NHibernate.Driver;
using NHibernate.SqlTypes;
namespace MySqlServerCeDriverNamespace
{
/// <summary>
/// Overridden Nhibernate SQL CE Driver,
/// so that ntext fields are not truncated at 4000 characters
/// </summary>
public class MySqlServerCeDriver : SqlServerCeDriver
{
protected override void InitializeParameter(
IDbDataParameter dbParam,
string name,
SqlType sqlType)
{
base.InitializeParameter(dbParam, name, sqlType);
if (sqlType is StringClobSqlType)
{
var parameter = (SqlCeParameter)dbParam;
parameter.SqlDbType = SqlDbType.NText;
}
}
}
}
Затем используйте этот драйвер вместо NHibernate в вашем app.config
<nhibernateDriver>MySqlServerCeDriverNamespace.MySqlServerCeDriver , MySqlServerCeDriverNamespace</nhibernateDriver>
Я видел много других постов, где люди сталкивались с этой проблемой, и решил ее, просто изменив атрибут sql-type на "StringClob" - как это пыталось сделать в этой теме.
Я не уверен, почему это не будет работать для меня, но я подозреваю, что это тот факт, что я использую SQL CE, а не какую-то другую БД. Но у вас есть это!
<property name="Value" type="string" />
<column name="Value" sql-type="StringClob" />
</property>
Я предполагаю, что это небольшая опечатка, так как вы дважды закрыли тег свойства. Просто указав на это, на случай, если это не опечатка.
Пытался:
<property name="Value" type="string" length="4001" />
а также
<property name="Value" type="string" >
<column name="Value" sql-type="StringClob" length="5000"/>
</property>
Боюсь, ни одна из них не сработала... То же самое исключение - все равно говорится, что максимальное значение равно 4000.
Почему вы используете синтаксис подэлемента?
пытаться:
<property name='Value' type='StringClob' />
После прочтения вашего поста эта модификация заработала в моем коде
protected override void InitializeParameter(IDbDataParameter dbParam,string name,SqlType sqlType)
{
base.InitializeParameter(dbParam, name, sqlType);
var stringType = sqlType as StringSqlType;
if (stringType != null && stringType.LengthDefined && stringType.Length > 4000)
{
var parameter = (SqlCeParameter)dbParam;
parameter.SqlDbType = SqlDbType.NText;
}
}
В моем текущем депломенте SQL CE и NHibernate я использую длину 4001. Затем NHibernate генерирует материал как NTEXT вместо NVARCHAR.
Попробуй это.
Еще одна вещь, которую можно использовать с NHibernate и SQL CE:
<session-factory>
...
<property name="connection.release_mode">on_close</property>
</session-factory>
Это решает некоторые другие проблемы для меня, по крайней мере.
Пытаться <property name="Value" type="string" length="4001" />