2012-08-24 14 views
13

tenemos una tabla de SQL Server con columnas max varchar y nvarchar así:cómo asignar una columna VARCHAR (MAX) en NHibernate hbm.xml archivos de asignación

CREATE TABLE [dbo].[MyTable](
    : 
    [MyBigUnicodeColumn] [nvarchar](max) NULL, 
    [MyBigAnsiColumn] [varchar](max) NULL, 
    : 

Al crear el mapeo (hbm.xml) archivos, el documentation 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.

Respuesta

20

Puede asignarlos como string o AnsiString.

<property name="MyBigUnicodeColumn" type="string" length="1000000"/> 
<property name="MyBigAnsiColumn" type="AnsiString" length="1000000" /> 

Siempre que la longitud es más grande que 4000 o 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: Por desgracia, no funciona con el AnsiString lo mismo 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)"); 

Se registra varchar (max) como el tipo SQL para elegir cuando un AnsiString se asigna más grande entonces 8000.

En el SqlClientDriver.cs se 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 incoherencia 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).Es necesario utilizar la solución propuesta en el thread you started on the NH forum:

<property name="MyBigAnsiColumn" type="StringClob" sql-type="VARCHAR(max)" /> 

me informó que como un error: https://nhibernate.jira.com/browse/NH-3252

+0

AnsiString es por definición una cadena no Unicode, por lo que este no sea quebrantada. Creo que esto solo cambiaría si futuros Servidores SQL ofrecieran nuevas formas de almacenar una cadena o una cadena ansi en la longitud especificada. –

+0

Por otro lado, todo esto se implementa en el dialecto, y es bastante fácil tener su propio dialecto. –

+0

Esto depende de la versión de NH que esté utilizando. Especifican la longitud al pasar los parámetros, para hacer que SQL Server reutilice las consultas. El cliente de SQL Server solía cortar datos, lo que era muy malo, por lo que verificaba la longitud. Si desea utilizar el agujero de 2 GB de longitud máxima, especifíquelo así ... –

0

usuario de 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 porque decidí convertir todas las columnas VARCHAR (MAX) a NVARCHAR (MAX) en su lugar.

1
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 hibernate.cfg.xml archivo:

<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"/> 

Cuestiones relacionadas