New to both NHibernate and Fluent NHibernate and I'm trying to resolve a performance problem in some inherited code caused by a conversion of a CHAR(10)
column to NVARCHAR
.
From SQL Profiler:
exec sp_executesql N'select mytestclas0_.LinkId as LinkId45_,
mytestclas0_.Href as Href45_,
mytestclas0_.LinkActive as LinkActive45_
from MessageLinks mytestclas0_
where mytestclas0_.LinkId=@p0',N'@p0 nvarchar(4000)',@p0=N'BzE2T48HMF'
You can see the ID coming in from NHibernate is cast as a NVARCHAR
.
Table definition:
CREATE TABLE [dbo].[MyTable](
[ID] [int] NULL,
[Href] [nvarchar](1000) NULL,
[LinkActive] [bit] NOT NULL,
[LinkId] [char](10) NOT NULL
)
The class file:
public class MyTestClass {
public MyTestClass() {}
public virtual string LinkId{ get; set; }
public virtual string Href{ get; set; }
public virtual bool LinkActive { get; set; }
}
The mapping file:
public class MyTestClassMapping : ClassMap<MyTestClass> {
public MyTestClassMapping() {
Table("MyTable");
Id(x => x.LinkId).Length(10);
Map(x => x.LinkId);
Map(x => x.Href);
Map(x => x.LinkActive);
}
}
I have tried a number of different things with the datatype of the LinkId and the mapping file, including these mappings:
Id(x => x.LinkId).CustomSqlType("char(10)");
Id(x => x.LinkId).Length(10).CustomSqlType("char");
Id(x => x.LinkId).CustomSqlType("char");
I'm looking for a pointer to an example or documentation that explains how to get the ID passed in by NHibernate cast to a CHAR(10)
.
Thanks in advance for any help.
The mapping should be like this (see the documentation 5.2.2. Basic value types):
Id(x => x.LinkId)
.CustomType("AnsiString")
...
;
NHibernate type for char
(non unicode string) is type="AnsiString"
for xml mapping. the above is the way how to do that in fluent.
See similar story here: NHibernate Performance (Ansi String vs. Unicode String)
Side Note: I've never managed to specify length ... always it is generated by NHibernate varchar(8000), using MS SQL 2008 dialect...
NHibernate MsSql2000Dialect and following versions define AnsiString correctly, also supporting length etc.
But, the current implementation of the SqlDriver got a change last year, see https://nhibernate.jira.com/browse/NH-3036 for details of the fix.
The code does now ignore the specified length and always uses the default. Default for AnsiString and some others is varchar(8000)
RegisterColumnType(DbType.AnsiString, SqlClientDriver.MaxSizeForLengthLimitedAnsiString, "VARCHAR($l)");
code from SqlDriver: setting default:
protected static void SetDefaultParameterSize(IDbDataParameter dbParam, SqlType sqlType)
{
switch (dbParam.DbType)
{
case DbType.AnsiString:
case DbType.AnsiStringFixedLength:
dbParam.Size = MaxSizeForLengthLimitedAnsiString;
break;
Bugfix:
// 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;
}
}
This of cause means no matter what you specify, it will not matter at all for the parameters. One can argue if this change is a good thing or not, I guess it is not ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With