How does one make NHibernate stop using nvarchar(4000) for insert parameter strings?
Specify the Type
as NHibernateUtil.AnsiString
with a Length
instead of using a CustomSqlType.
This issue can cause a huge performance problem in queries if it forces SQL Server to perform a table scan instead of using an index. We use varchar throughout our database so I created a convention to set the type globally:
/// <summary>/// Convert all string properties to AnsiString (varchar). This does not work with SQL CE./// </summary>public class AnsiStringConvention : IPropertyConventionAcceptance, IPropertyConvention{ public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria) { criteria.Expect(x => x.Property.PropertyType.Equals(typeof(string))); } public void Apply(IPropertyInstance instance) { instance.CustomType("AnsiString"); }}
Okay this is what we have to do, the SQLClientDriver
ignores the length property of the SqlType
. So we created a our own driverclass inheriting from SQLClientDriver
and override the method GenerateCommand
...Something like this:
public override IDbCommand GenerateCommand(CommandType type, NHibernate.SqlCommand.SqlString sqlString, SqlType[] parameterTypes){ var dbCommand = base.GenerateCommand(type, sqlString, parameterTypes); SetParameterSizes(dbCommand.Parameters, parameterTypes); return dbCommand;}private static void SetParameterSizes(IDataParameterCollection parameters, SqlType[] parameterTypes){ for (int index = 0; index < parameters.Count; ++index) SetVariableLengthParameterSize((IDbDataParameter)parameters[index], parameterTypes[index]);}private static void SetVariableLengthParameterSize(IDbDataParameter dbParam, SqlType sqlType){ SetDefaultParameterSize(dbParam, sqlType); if (sqlType.LengthDefined && !IsText(dbParam, sqlType) && !IsBlob(dbParam, sqlType)) dbParam.Size = sqlType.Length; if (!sqlType.PrecisionDefined) return; dbParam.Precision = sqlType.Precision; dbParam.Scale = sqlType.Scale;}