2012-07-09 16 views
5

¿Hay alguna manera de especificar una tabla para usar para valores Hi-Lo, con cada entidad que tenga una entrada por fila, mediante una convención (mientras si todavía tienes nHibernate, crea la estructura de la tabla para ti)? Me gustaría replicar lo que Phil Haydon escribió en el blog sobre here, pero sin tener que administrar manualmente la tabla. Tal como está, migrar su código de fila por tabla a su propia convención solo funcionará si ya ha creado las entradas apropiadas para 'TableKey' en la tabla.Fluidez nHibernate, tabla Hi-Lo con entidad por fila mediante una convención

Alternativamente, ¿esto es posible a través de las asignaciones de XML?

Y si todo lo demás falla, ¿es la única otra opción adecuada para usar un generador personalizado, a la this post?

Respuesta

8

Fabio Maulo talked about this en una de sus publicaciones de mapas por código.

Mapeo por ejemplo de código:

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

Para FluentNHibernate, que podría hacer algo como:

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

Además, Fabio se explica cómo se puede utilizar para crear IAuxiliaryDatabaseObject guión Hi-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 
     }); 
} 

Se podría utilizar de esta manera:

configuration.AddAuxiliaryDatabaseObject(CreateHighLowScript(
    modelInspector, Assembly.GetExecutingAssembly().GetExportedTypes())); 
2

edificio fuera de la ya excelente solución de Anthony Dewhirst , Terminé con lo siguiente, que agrega un par de mejoras:

  • Agrega criterios de aceptación para que no intente manejar tipos de Id no integrales (p. Guid) y no va a pisar fuerte en las asignaciones de ID que tiene un generador establece explícitamente
  • generación de script toma en consideración dialecto
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)); 
    } 
} 
Cuestiones relacionadas