Fluente NHibernate che associa a una colonna ID CHAR (10) di SQL Server

Nuovo per NHibernate e Fluent NHibernate e sto cercando di risolvere un problema di prestazioni in qualche codice ereditato causato da una conversione di una colonna CHAR(10) in NVARCHAR .

Da SQL Profiler:

 exec sp_executesql N'select mytestclas0_.LinkId as LinkId45_, mytestclas0_.Href as Href45_, mytestclas0_.LinkActive as LinkActive45_ from MessageLinks mytestclas0_ where [email protected]',N'@p0 nvarchar(4000)',@p0=N'BzE2T48HMF' 

Puoi vedere che l’ID che arriva da NHibernate viene lanciato come NVARCHAR .

Definizione tabella:

 CREATE TABLE [dbo].[MyTable]( [ID] [int] NULL, [Href] [nvarchar](1000) NULL, [LinkActive] [bit] NOT NULL, [LinkId] [char](10) NOT NULL ) 

Il file di class:

 public class MyTestClass { public MyTestClass() {} public virtual string LinkId{ get; set; } public virtual string Href{ get; set; } public virtual bool LinkActive { get; set; } } 

Il file di mapping:

  public class MyTestClassMapping : ClassMap { public MyTestClassMapping() { Table("MyTable"); Id(x => x.LinkId).Length(10); Map(x => x.LinkId); Map(x => x.Href); Map(x => x.LinkActive); } } 

Ho provato un certo numero di cose diverse con il tipo di dati del LinkId e il file di mapping, compresi questi mapping:

  Id(x => x.LinkId).CustomSqlType("char(10)"); Id(x => x.LinkId).Length(10).CustomSqlType("char"); Id(x => x.LinkId).CustomSqlType("char"); 

Sto cercando un puntatore a un esempio o documentazione che spiega come ottenere l’ID passato dal cast di NHibernate a un CHAR(10) .

Grazie in anticipo per qualsiasi aiuto.

La mapping dovrebbe essere come questa (consultare la documentazione 5.2.2 Tipi di valori di base ):

 Id(x => x.LinkId) .CustomType("AnsiString") ... ; 

Il tipo NHibernate per char (stringa non unicode) è type="AnsiString" per la mapping xml. quanto sopra è il modo in cui farlo in modo fluente.

Guarda la storia simile qui: Performance di NHibernate (stringa Ansi vs. stringa Unicode)

Nota a margine: non sono mai riuscito a specificare la lunghezza … sempre è generato da NHibernate varchar (8000), usando il dialetto MS SQL 2008 …

NHibernate MsSql2000Dialect e le seguenti versioni definiscono AnsiString correttamente, supportando anche la lunghezza, ecc.

Ma l’attuale implementazione di SqlDriver ha avuto un cambiamento lo scorso anno, vedere https://nhibernate.jira.com/browse/NH-3036 per i dettagli della correzione.

Il codice ora ignora la lunghezza specificata e utilizza sempre il valore predefinito. Il valore predefinito per AnsiString e alcuni altri è varchar (8000)

 RegisterColumnType(DbType.AnsiString, SqlClientDriver.MaxSizeForLengthLimitedAnsiString, "VARCHAR($l)"); 

codice da SqlDriver: impostazione predefinita:

 protected static void SetDefaultParameterSize(IDbDataParameter dbParam, SqlType sqlType) { switch (dbParam.DbType) { case DbType.AnsiString: case DbType.AnsiStringFixedLength: dbParam.Size = MaxSizeForLengthLimitedAnsiString; break; 

Risoluzione del problema:

  // Used from SqlServerCeDriver as well public static void SetVariableLengthParameterSize(IDbDataParameter dbParam, SqlType sqlType) { SetDefaultParameterSize(dbParam, sqlType); // no longer override the defaults using data from SqlType, since LIKE expressions needs larger columns // https://nhibernate.jira.com/browse/NH-3036 //if (sqlType.LengthDefined && !IsText(dbParam, sqlType) && !IsBlob(dbParam, sqlType)) //{ // dbParam.Size = sqlType.Length; //} if (sqlType.PrecisionDefined) { dbParam.Precision = sqlType.Precision; dbParam.Scale = sqlType.Scale; } } 

Ciò significa che, indipendentemente da ciò che si specifica, non avrà alcuna importanza per i parametri. Si può discutere se questo cambiamento è una cosa buona o no, immagino che non lo sia;)

Questa è una supposizione, dato che ho usato CustomSqlType, ma non personalmente con char.

  Id(x => x.LinkId).Length(10).CustomSqlType("char(10)"); 

o potresti dover perdere la lunghezza.

  Id(x => x.LinkId).CustomSqlType("char(10)"); 

Ecco un simiar:

È ansible utilizzare CustomSqlType con CompositeId?