2012-08-24 34 views
13

Chúng tôi có một bảng SQL Server với các cột max varchar và nvarchar như thế này:Làm thế nào để lập bản đồ một cột VARCHAR (MAX) trong các tập tin bản đồ NHibernate hbm.xml

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

Khi tạo ánh xạ (hbm.xml) tập tin, các documentation nói để sử dụng StringClob là thuộc tính type cho các đối tượng lớn với một kiểu cơ sở dữ liệu của DbType.String, nhưng nó không nói phải làm gì nếu kiểu cơ sở dữ liệu là DbType.AnsiString.

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

Điều này dành cho NHibernate 3.3.1.

Trả lời

20

Bạn có thể ánh xạ chúng dưới dạng string hoặc AnsiString.

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

Bất cứ khi nào chiều dài lớn hơn 4000 hoặc 8000 tương ứng, NH tạo ra một nvarchar (tối đa) hoặc varchar (tối đa).

Tôi có thể là độ dài được sử dụng cho tham số sql và nó được cắt ngắn đến độ dài được chỉ định (tùy thuộc vào phiên bản NH bạn đang sử dụng, đã có một số thay đổi). Vì vậy, tốt hơn chỉ định nó đủ lớn.


Sửa: Thật không may, nó không hoạt động với AnsiString giống như với chuỗi bình thường. Tôi đọc một số mã NH và tìm thấy những điều sau đây:

varchar (tối đa) được hỗ trợ bởi phương ngữ từ SQL Server 2005 trên.

MsSql2000Dialect.cs, dòng 205

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

MsSql2005Dialect.cs, dòng 19:

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

Nó đăng ký varchar (max) như các loại sql để lựa chọn khi một AnsiString được ánh xạ lớn hơn sau đó 8000.

Trong SqlClientDriver.cs bạn có thể thấy rằng nó thực hiện "các đốm" trong các tham số cho chuỗi, nhưng không phải cho các chuỗi ansi (dòng 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; 

Nó luôn đặt 8000 là giới hạn của tham số kiểu AnsiString.

Vì sự không nhất quán giữa người lái và phương ngữ, tôi sẽ gọi đó là lỗi.

Vì lỗi xảy ra trên tất cả AnsiStrings, nó không giúp xác định loại sql trong ánh xạ (NH có thể chọn kiểu sql chính xác).Bạn cần phải sử dụng workaround đề xuất trong thread you started on the NH forum:

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

Tôi đã báo cáo nó như là một lỗi: https://nhibernate.jira.com/browse/NH-3252

+0

AnsiString là theo định nghĩa một chuỗi không unicode, vì vậy điều này không nên bị phá vỡ. Tôi nghĩ rằng điều này sẽ chỉ thay đổi nếu các máy chủ SQL trong tương lai sẽ cung cấp các cách mới để lưu trữ một chuỗi hoặc một chuỗi ansi theo chiều dài được chỉ định. –

+0

Ở phía bên kia, điều này là tất cả được thực hiện trong các phương ngữ, và nó là khá dễ dàng để có phương ngữ của riêng bạn. –

+0

Điều này tùy thuộc vào phiên bản NH bạn đang sử dụng. Chúng chỉ định độ dài khi truyền các tham số, để làm cho SQL Server sử dụng lại các truy vấn. Máy khách SQL Server được sử dụng để cắt dữ liệu, điều này rất tệ, vì vậy hãy kiểm tra độ dài. Nếu bạn muốn sử dụng chiều dài tối đa lỗ 2 GB, hãy chỉ định nó như thế này ... –

0

tài Nexus trên (nhusers) diễn đàn NHibernate nói:

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

Lưu ý: Tôi chưa xác minh điều này vì tôi quyết định chuyển đổi tất cả các cột VARCHAR (MAX) thành 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; 
    } 

} 

Và hibernate.cfg.xml file:

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

Các vấn đề liên quan