【问题标题】:Fluent nHibernate, Hi-Lo table with entity-per-row using a conventionFluent nHibernate,Hi-Lo 表,每行实体使用约定
【发布时间】:2012-07-09 20:28:58
【问题描述】:

有没有办法通过约定来指定用于 Hi-Lo 值的表,每个实体都有一个每行条目(同时仍然让 nHibernate 为您创建表结构)?我想复制 Phil Haydon 写的关于 here 的博客,但不必手动管理表格。就目前而言,仅当您已经在表中为“TableKey”创建了适当的条目时,将他的每表行代码迁移到它自己的约定才有效。

或者,这可以通过 XML 映射实现吗?

如果所有其他方法都失败了,那么使用自定义生成器的唯一其他合适的选择是this post

【问题讨论】:

    标签: nhibernate fluent-nhibernate


    【解决方案1】:

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

    此外,Fabio 解释了如何使用 IAuxiliaryDatabaseObject 创建 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 
            });
    }
    

    你会这样使用它:

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

    【讨论】:

      【解决方案2】:

      对于 Fluent NHibernate 的用户,Anthony Dewhirst 在这里发布了一个不错的解决方案:http://www.anthonydewhirst.blogspot.co.uk/2012/02/fluent-nhibernate-solution-to-enable.html

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-24
          • 1970-01-01
          相关资源
          最近更新 更多