many - Cómo asignar una columna VARCHAR(MAX) en los archivos de mapeo NHibernate hbm.xml
nhibernate sessionfactory connection string (3)
El usuario Nexus en el foro NHibernate (nhusers) dijo:
<property name="MyBigAnsiColumn" type="StringClob" sql-type="VARCHAR(max)" />
Should be the most correct answer
Nota: No he verificado esto ya que decidí convertir todas las columnas VARCHAR (MAX) a NVARCHAR (MAX) en su lugar.
Tenemos una tabla de SQL Server con varchar y nvarchar max columnas como esta:
CREATE TABLE [dbo].[MyTable](
:
[MyBigUnicodeColumn] [nvarchar](max) NULL,
[MyBigAnsiColumn] [varchar](max) NULL,
:
Al crear los archivos de mapeo (hbm.xml), la documentación dice que use StringClob como el atributo de tipo para objetos grandes con un tipo de base de datos de DbType.String, pero no dice qué hacer si el tipo de base de datos es DbType.AnsiString .
<class name="MyTable" table="MyTable" lazy="false">
:
<property name="MyBigUnicodeColumn" type="StringClob" />
<property name="MyBigAnsiColumn" type="????" />
:
Esto es para NHibernate 3.3.1.
Puede AnsiString
solo como string
o AnsiString
.
<property name="MyBigUnicodeColumn" type="string" length="1000000"/>
<property name="MyBigAnsiColumn" type="AnsiString" length="1000000" />
Siempre que la longitud sea mayor que 4000 u 8000 respectivamente, NH crea un nvarchar (max) o varchar (max).
Puede ser que la longitud se use para los parámetros sql y que se trunque a la longitud especificada (depende de la versión de NH que esté utilizando, hubo algunos cambios). Así que mejor especifique lo suficientemente grande.
Editar : Desafortunadamente, no funciona con AnsiString igual que con las cadenas normales. Leí un código NH y encontré lo siguiente:
varchar (max) es compatible con el dialecto de SQL Server 2005 en.
MsSql2000Dialect.cs, línea 205
RegisterColumnType(DbType.AnsiString, SqlClientDriver.MaxSizeForLengthLimitedAnsiString, "VARCHAR($l)");
MsSql2005Dialect.cs, línea 19:
RegisterColumnType(DbType.AnsiString, SqlClientDriver.MaxSizeForAnsiClob, "VARCHAR(MAX)");
Registra varchar (max) como el tipo sql para elegir cuando un AnsiString se mapea más grande que 8000.
En SqlClientDriver.cs, puede ver que implementa "blobs" en los params para cadenas, pero no para strings ansi (línea 135):
case DbType.AnsiString:
case DbType.AnsiStringFixedLength:
dbParam.Size = MaxSizeForLengthLimitedAnsiString;
break;
// later on
case DbType.String:
case DbType.StringFixedLength:
dbParam.Size = IsText(dbParam, sqlType) ? MaxSizeForClob : MaxSizeForLengthLimitedString;
break;
Siempre pone 8000 como el límite del parámetro de tipo AnsiString.
Debido a la inconsistencia entre el controlador y el dialecto, lo llamaría un error.
Debido a que el error ocurre en todas las AnsiStrings, no ayuda a especificar el tipo sql en la asignación (NH puede elegir el tipo de SQL correcto). Debe utilizar la solución alternativa propuesta en el hilo que comenzó en el foro de NH :
<property name="MyBigAnsiColumn" type="StringClob" sql-type="VARCHAR(max)" />
Lo informé como un error: https://nhibernate.jira.com/browse/NH-3252
public class Role
{
public Role() { }
public virtual string RoleId { get; set; }
public virtual string RoleName { get; set; }
public virtual string RoleDescription { get; set; }
}
public class RoleMap : ClassMapping<Role>
{
public RoleMap()
{
Table("nda_roles");
Schema("dbo");
Lazy(true);
Id(x => x.RoleId, map =>
{
map.Column("role_id");
map.Length(12);
map.Type((IIdentifierType)TypeFactory.GetAnsiStringType(12));
map.Generator(Generators.Assigned);
});
Property(x => x.RoleName, map =>
{
map.Column("role_name");
map.NotNullable(true);
map.Length(50);
map.Type(TypeFactory.GetAnsiStringType(50));
});
Property(x => x.RoleDescription, map =>
{
map.Column("role_description");
map.Length(NHibernateConfig.GetMaxLengthAnsiString());
map.Type(TypeFactory.GetAnsiStringType(NHibernateConfig.GetMaxLengthAnsiString()));
});
}
}
public static class NHibernateConfig
{
private static string driver_class;
private static string dialect;
public static ISessionFactory GetNHibernateSessionFactory()
{
var config = new Configuration().Configure(); // Read config from hibernate.cfg.xml
var configPath = HttpContext.Current.Server.MapPath(@"~/hibernate.cfg.xml");
config.Configure(configPath);
driver_class = config.Properties["connection.driver_class"];
dialect = config.Properties["dialect"];
config.CurrentSessionContext<WebSessionContext>();
var mapper = new ModelMapper();
mapper.AddMappings(new Type[]
{
typeof(NDA.Models.RoleMap),
typeof(NDA.Models.PermissionMap),
typeof(NDA.Models.CompanyMap),
typeof(NDA.Models.UserMap),
});
HbmMapping domainMapping = mapper.CompileMappingForAllExplicitlyAddedEntities();
config.AddMapping(domainMapping);
new SchemaExport(config).Execute(false, true, false);
return config.BuildSessionFactory();
}
public static int GetMaxLengthString()
{
int maxlenght = 255;
switch (driver_class)
{
case "NHibernate.Driver.SqlClientDriver":
switch (dialect)
{
case "NHibernate.Dialect.MsSql2008Dialect":
maxlenght = 4000;
break;
}
break;
}
return maxlenght;
}
public static int GetMaxLengthAnsiString()
{
int maxlenght = 255;
switch (driver_class)
{
case "NHibernate.Driver.SqlClientDriver":
switch (dialect)
{
case "NHibernate.Dialect.MsSql2008Dialect":
maxlenght = 8000;
break;
}
break;
}
return maxlenght;
}
}
Y el archivo hibernate.cfg.xml:
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" >
<session-factory name="NHibernate.NDA">
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="connection.connection_string_name">nda_connectionstring</property>
<property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
<property name="hbm2ddl.auto">validate</property>
<mapping assembly="NDA"/>