NHibernate nvarchar/ntext problema di troncamento
-
02-07-2019 - |
Domanda
Sto usando nhibernate per memorizzare alcune impostazioni utente per un'applicazione in un database di SQL Server Compact Edition tabella.
Questo è un estratto del file di mapping:
<property name="Name" type="string" />
<property name="Value" type="string" />
Il nome è una stringa regolare/nvarchar(50), e il Valore è impostato come tipo di dati ntext nel DB
Sto cercando di scrivere una grande quantità di xml per il "Valore" di proprietà.Ottengo un'eccezione ogni volta che:
@p1 : String truncation: max=4000, len=35287, value='<lots of xml..../>'
Ho googlato un bel po', e provato un certo numero di diversi mappatura configurazioni:
<property name="Name" type="string" />
<property name="Value" type="string" >
<column name="Value" sql-type="StringClob" />
</property>
Questo è un esempio.Altre configurazioni includono "tipo di dati ntext" invece di "StringClob".Quelle configurazioni che non passi la mappatura eccezioni ancora lanciare la stringa di troncamento eccezione.
Questo è un problema ("funzione") con SQL CE?È possibile inserire più di 4000 caratteri in un database di SQL CE con nhibernate?Se è così, qualcuno può dirmi come?
Molte grazie!
Soluzione
Ok, molte grazie per Artur in questo thread, ecco la soluzione:Ereditano dalla SqlServerCeDriver con uno nuovo, e ignorare il InitializeParamter metodo:
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;
}
}
}
}
Quindi, utilizzare questo driver invece di NHibernate nella tua app.config
<nhibernateDriver>MySqlServerCeDriverNamespace.MySqlServerCeDriver , MySqlServerCeDriverNamespace</nhibernateDriver>
Ho visto un sacco di altri posti dove la gente ha questo problema e risolto da solo di cambiare il sql-tipo di attributo di "StringClob" - come ha tentato in questo thread.
Non so perché non funziona per me, ma ho il sospetto che sia il fatto che sto usando SQL CE e non di qualche altro DB.Ma, non c'è l'ho!
Altri suggerimenti
<property name="Value" type="string" />
<column name="Value" sql-type="StringClob" />
</property>
Suppongo che questo sia un piccolo errore di battitura, poiché hai chiuso il tag proprietà due volte. Basta sottolineare questo, nel caso in cui non fosse un refuso.
Prova <property name="Value" type="string" length="4001" />
Hai provato:
<property name="Value" type="string" length="4001" />
e
<property name="Value" type="string" >
<column name="Value" sql-type="StringClob" length="5000"/>
</property>
Né ha funzionato, temo ... Stessa eccezione - dice ancora che il valore massimo è 4000.
Perché stai usando la sintassi dell'elemento secondario?
Prova:
<property name='Value' type='StringClob' />
Nel mio attuale deplyoment di SQL CE e NHibernate utilizzo una lunghezza di 4001. Quindi NHibernate genera le cose come NTEXT anziché NVARCHAR.
Prova.
Un'altra cosa da usare con NHibernate e SQL CE è:
<session-factory>
...
<property name="connection.release_mode">on_close</property>
</session-factory>
Questo risolve alcuni altri problemi per me almeno.
Dopo aver letto il tuo post questa modifica l'ha fatto funzionare nel mio codice
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;
}
}