5

Hi-Lo 値に使用するテーブルを指定する方法はありますか?各エンティティには行ごとのエントリがあり、規則を介して (nHibernate にテーブル構造を作成させながら)? Phil Haydon がここでブログについて書いたことを複製したいと思いますが、テーブルを手動で管理する必要はありません。現状では、彼のテーブルごとの行コードを独自の規則に移行することは、テーブルに「TableKey」の適切なエントリを既に作成している場合にのみ機能します。

あるいは、これは XML マッピングを介して可能ですか?

そして、他のすべてが失敗した場合、この投稿のように、カスタムジェネレーターを使用する唯一の適切なオプションはありますか?

4

3 に答える 3

9

Fabio Mauloは、彼のコードによるマッピングの投稿の1つでこれについて話しました。

コード例によるマッピング:

mapper.BeforeMapClass += (mi, type, map) =>
    map.Id(idmap => idmap.Generator(Generators.HighLow,
        gmap => gmap.Params(new
        {
            table = "NextHighValues",
            column = "NextHigh",
            max_lo = 100,
            where = string.Format(
                "EntityName = '{0}'", type.Name.ToLowerInvariant())
        })));

FluentNHibernateの場合、次のようなことができます。

public class PrimaryKeyConvention : IIdConvention
{
    public void Apply(IIdentityInstance instance)
    {
        var type = instance.EntityType.Name;
        instance.Column(type + "Id");
        instance.GeneratedBy.HiLo(type, "NextHigh", "100", 
            x => x.AddParam("where", String.Format("EntityName = '{0}'", type));
    }
}

また、Fabioは、IAuxiliaryDatabaseObjectHi-Loスクリプトを作成するためにどのように使用できるかを説明しました。

private static IAuxiliaryDatabaseObject CreateHighLowScript(
    IModelInspector inspector, IEnumerable<Type> entities)
{
    var script = new StringBuilder(3072);
    script.AppendLine("DELETE FROM NextHighValues;");
    script.AppendLine(
        "ALTER TABLE NextHighValues ADD EntityName VARCHAR(128) NOT NULL;");
    script.AppendLine(
        "CREATE NONCLUSTERED INDEX IdxNextHighValuesEntity ON NextHighValues " 
        + "(EntityName ASC);");
    script.AppendLine("GO");

    foreach (var entity in entities.Where(x => inspector.IsRootEntity(x)))
    {
        script.AppendLine(string.Format(
         "INSERT INTO [NextHighValues] (EntityName, NextHigh) VALUES ('{0}',1);",
         entity.Name.ToLowerInvariant()));
    }

    return new SimpleAuxiliaryDatabaseObject(
        script.ToString(), null, new HashedSet<string> {
           typeof(MsSql2005Dialect).FullName, typeof(MsSql2008Dialect).FullName 
        });
}

次のように使用します。

configuration.AddAuxiliaryDatabaseObject(CreateHighLowScript(
    modelInspector, Assembly.GetExecutingAssembly().GetExportedTypes()));
于 2012-07-09T20:55:39.477 に答える
2

Anthony Dewhirst の既に優れたソリューションに基づいて構築した結果、次のようになりました。これには、いくつかの改善が追加されています。

  • 非整数の Id タイプ (例: Guid) を処理しようとせず、ジェネレーターが明示的に設定されている Id マッピングを踏みにじらないように、受け入れ基準を追加します。
  • 方言を考慮したスクリプト生成
public class HiLoIdGeneratorConvention : IIdConvention, IIdConventionAcceptance
{
    public const string EntityColumnName = "entity";
    public const string MaxLo = "500";

    public void Accept(IAcceptanceCriteria<IIdentityInspector> criteria)
    {
        criteria
            .Expect(x => x.Type == typeof(int) || x.Type == typeof(uint) || x.Type == typeof(long) || x.Type == typeof(ulong)) // HiLo only works with integral types
            .Expect(x => x.Generator.EntityType == null); // Specific generator has not been mapped
    }

    public void Apply(IIdentityInstance instance)
    {
        instance.GeneratedBy.HiLo(TableGenerator.DefaultTableName, TableGenerator.DefaultColumnName, MaxLo,
                                  builder => builder.AddParam(TableGenerator.Where, string.Format("{0} = '{1}'", EntityColumnName, instance.EntityType.FullName)));
    }

    public static void CreateHighLowScript(NHibernate.Cfg.Configuration config)
    {
        var dialect = Activator.CreateInstance(Type.GetType(config.GetProperty(NHibernate.Cfg.Environment.Dialect))) as Dialect;
        var script = new StringBuilder();

        script.AppendFormat("DELETE FROM {0};", TableGenerator.DefaultTableName);
        script.AppendLine();
        script.AppendFormat("ALTER TABLE {0} {1} {2} {3} NOT NULL;", TableGenerator.DefaultTableName, dialect.AddColumnString, EntityColumnName, dialect.GetTypeName(SqlTypeFactory.GetAnsiString(128)));
        script.AppendLine();
        script.AppendFormat("CREATE NONCLUSTERED INDEX IX_{0}_{1} ON {0} ({1} ASC);", TableGenerator.DefaultTableName, EntityColumnName);
        script.AppendLine();
        if (dialect.SupportsSqlBatches)
        {
            script.AppendLine("GO");
            script.AppendLine();
        }
        foreach (var entityName in config.ClassMappings.Select(m => m.EntityName).Distinct())
        {
            script.AppendFormat("INSERT INTO [{0}] ({1}, {2}) VALUES ('{3}',1);", TableGenerator.DefaultTableName, EntityColumnName, TableGenerator.DefaultColumnName, entityName);
            script.AppendLine();
        }
        if (dialect.SupportsSqlBatches)
        {
            script.AppendLine("GO");
            script.AppendLine();
        }

        config.AddAuxiliaryDatabaseObject(new SimpleAuxiliaryDatabaseObject(script.ToString(), null));
    }
}
于 2014-08-27T15:02:16.930 に答える
2

Fluent NHibernate のユーザー向けに、Anthony Dewhirst が優れたソリューションをここに投稿しています: http://www.anthonydewhirst.blogspot.co.uk/2012/02/fluent-nhibernate-solution-to-enable.html

于 2012-09-10T09:51:42.927 に答える