2012-08-24 4 views
13

NHibernate에 hbm.xml 매핑 파일에서 VARCHAR (MAX) 열을 매핑하는 방법 :우리는이 같은 VARCHAR 및 NVARCHAR 최대 열이있는 SQL Server 테이블이

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

매핑을 생성 (hbm.xml를) 파일의 경우 documentation은 데이터베이스 유형이 DbType.String 인 대형 객체의 유형 특성으로 StringClob을 사용하지만 데이터베이스 유형이 DbType.AnsiString 인 경우 수행 할 작업을 말하지 않습니다.

<class name="MyTable" table="MyTable" lazy="false"> 
    : 
    <property name="MyBigUnicodeColumn" type="StringClob" /> 
    <property name="MyBigAnsiColumn" type="????" /> 
    : 

이것은 NHibernate 3.3.1에 대한 것입니다.

답변

20

string 또는 AnsiString과 같이 매핑 할 수 있습니다.

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

길이가 각각 4000 또는 8000 그때마다 큰

는 NH는 NVARCHAR (최대) 또는 VARCHAR (max)를 생성한다.

길이가 SQL 매개 변수에 사용되고 길이가 지정된 길이로 잘릴 수 있습니다 (사용중인 NH 버전에 따라 일부 변경이있을 수 있음). 그래서 충분히 크게 지정하십시오.


편집는 : 불행하게도, 그것은 일반 문자열과 동일 AnsiString을 작동하지 않습니다. NH 코드를 읽고 다음을 찾았습니다.

varchar (max)는 SQL Server 2005의 dialect에서 지원됩니다.

MsSql2000Dialect.cs 라인 205

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

MsSql2005Dialect.cs 라인 19 : SQL 형 등

RegisterColumnType(DbType.AnsiString, SqlClientDriver.MaxSizeForAnsiClob, "VARCHAR(MAX)"); 

그것은 VARCHAR (최대) 레지스터는 다음의 AnsiString 큰 매핑되면 선택할 SqlClientDriver.cs에서 8000

당신이 아니라 ANSI 문자열 (라인 135)에 대한, 그것은 문자열에 대한 PARAMS에서 "모양"을 구현하는 것을 볼 수 있습니다

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; 

항상 AnsiString 유형의 매개 변수 한계로 8000을 넣습니다.

드라이버와 방언 사이의 불일치 때문에 버그라고 부를 것입니다.

버그는 모든 AnsiString에서 발생하기 때문에 NH에서 올바른 SQL 유형을 선택할 수있는 매핑에서 sql 유형을 지정하는 데 도움이되지 않습니다.https://nhibernate.jira.com/browse/NH-3252가 NHibernate에 (nhusers) 포럼에

+0

AnsiString과는 정의에 의해 비 유니 코드 문자열이기 때문에이 파괴되어서는 안된다. 미래의 SQL Server가 문자열이나 ansi 문자열을 지정된 길이로 저장하는 새로운 방법을 제공 할 경우에만 변경 될 것이라고 생각합니다. –

+0

다른 측면에서, 이것은 Dialect에서 모두 구현되며, 방언을 직접 작성하는 것은 매우 쉽습니다. –

+0

이것은 사용중인 NH 버전에 따라 다릅니다. SQL Server에서 쿼리를 다시 사용하도록 매개 변수를 전달할 때 길이를 지정합니다. SQL Server 클라이언트는 데이터를 차단하는 데 사용되어 매우 나빴습니다. 그래서 길이를 확인하십시오. 구멍을 2GB 최대 길이로 사용하려면 다음과 같이 지정하십시오. –

0

사용자 넥서스는 말했다 :

<property name="MyBigAnsiColumn" type="StringClob" sql-type="VARCHAR(max)" /> 
Should be the most correct answer 

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

내가 버그로보고 : 당신은 thread you started on the NH forum에서 제안 된 해결 방법을 사용할 필요가

참고 : 모든 VARCHAR (MAX) 열을 NVARCHAR (MAX)로 변환하기로 결정 했으므로이를 확인하지 않았습니다.

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; 
    } 

} 

그리고있는 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"/> 

관련 문제