2012-07-09 52 views
5

有沒有一種方法來指定一個表來使用Hi-Lo值,每個實體有一個每行條目,通過約定(while仍然有nHibernate爲你創建表結構)?我想複製Phil Haydon在here的博客,但不必手動管理表格。就目前而言,只有在表格中已經爲表格中的「TableKey」創建了適當的條目後,才能將他的每行表格代碼遷移到自己的約定。流利的nHibernate,Hi-Lo表與實體每行使用約定

另外,這是可能的通過XML映射?

如果一切都失敗了,是唯一一個使用自定義生成器的其他合適的選項,la this post

回答

8

Fabio Maulo talked about this在他的一個代碼映射職位。

映射的代碼示例:

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

此外,法比奧解釋瞭如何使用IAuxiliaryDatabaseObject創建高低腳本。

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())); 
2

大廈掉安東尼德惠斯特本已出色的解決方案,我結束了以下,它增加了一些改進:

  • 添加驗收標準,以便它不嘗試處理非整數的Id類型(例如, GUID)並不會在其上有一臺發電機明確設置標識映射跺腳
  • 腳本生成需要方言考慮
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)); 
    } 
} 
相關問題