17

次のようなvarchar列とnvarcharmax列を持つSQLServerテーブルがあります。

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

マッピング(hbm.xml)ファイルを作成するとき、ドキュメントには、データベースタイプがDbType.Stringのラージオブジェクトのタイプ属性としてStringClobを使用するように記載されていますが、データベースタイプがDbType.AnsiStringの場合の対処方法は記載されていません。 。

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

これはNHibernate3.3.1用です。

4

3 に答える 3

23

stringまたはのようにマッピングできますAnsiString

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

長さがそれぞれ 4000 または 8000 より大きい場合、NH は nvarchar(max) または varchar(max) を作成します。

長さがSQLパラメーターに使用され、指定された長さに切り捨てられている可能性があります(使用しているNHバージョンによって異なりますが、いくつかの変更がありました)。したがって、十分な大きさを指定することをお勧めします。


編集: 残念ながら、通常の文字列と同じように AnsiString では機能しません。NHコードを読んだところ、次のことがわかりました。

varchar(max) は、SQL Server 2005 以降の方言でサポートされています。

MsSql2000Dialect.cs、205 行目

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

MsSql2005Dialect.cs、19 行目:

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

AnsiString が 8000 を超えてマップされた場合に選択する sql 型として varchar(max) を登録します。

SqlClientDriver.cs では、文字列の params に "blob" が実装されていますが、ansi 文字列には実装されていないことがわかります (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;

AnsiString 型のパラメータの制限は常に 8000 です。

ドライバーと方言の不一致のため、私はこれをバグと呼んでいます。

このバグはすべての AnsiString で発生するため、マッピングで sql-type を指定しても役に立ちません (NH は正しい sql 型を選択できます)。NH フォーラムで開始したスレッドで提案されている回避策を使用する必要があります。

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

バグとして報告しました: https://nhibernate.jira.com/browse/NH-3252

于 2012-08-24T09:13:24.780 に答える
1

NHibernate (nhusers) フォーラムのユーザー Nexus は次のように述べています。

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

注: 代わりにすべての VARCHAR(MAX) 列を NVARCHAR(MAX) に変換することにしたため、これを確認していません。

于 2012-08-29T00:28:12.873 に答える
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"/>

于 2014-11-17T14:17:55.173 に答える