Fluent nhibernate 如何使用fluent nhibernate更改多列索引中的列顺序?

Fluent nhibernate 如何使用fluent nhibernate更改多列索引中的列顺序?,fluent-nhibernate,Fluent Nhibernate,如何更改多列索引中的列顺序? 即: 生成以下架构: create index IX_index on ApplicantProgramDatas (SomeField, SomeReferenceId) 但我想得到: create index IX_index on ApplicantProgramDatas (SomeReferenceId, SomeField) 我想这是不可能的FluentNHibernate.MappingModel.MappedMembers.AcceptVisit

如何更改多列索引中的列顺序?
即:

生成以下架构:

create index IX_index on ApplicantProgramDatas (SomeField, SomeReferenceId)
但我想得到:

create index IX_index on ApplicantProgramDatas (SomeReferenceId, SomeField)

我想这是不可能的FluentNHibernate.MappingModel.MappedMembers.AcceptVisitor()'在引用之前迭代属性:

        foreach (var collection in Collections)
            visitor.Visit(collection);

        foreach (var property in Properties)
            visitor.Visit(property);

        foreach (var reference in References)
            visitor.Visit(reference);
因此,在多列索引中,属性总是位于引用之前


顺便说一句,所有的ORM都不能让您设置非平凡的索引选项,如聚集、筛选等。

我建议您覆盖SchemaExport。有通过反射的私有字段访问器,需要完全信任模式。如果这种方法不适合你的需要,考虑改写SchemaExport(相对轻类)


您可以使用或IAuxiliaryDatabaseObject在NHibernate中定义索引

在hbm.xml文件中:

<hibernate-mapping xmlns="urn:nhiernate-mapping-2.2">
  <database-object>
     <create>VALID SQL</create>
     <drop>VALID SQL</create>
  </database-object>
</hibernate-mapping>
N.B.NHibernate.Mapping.SimpleUxiliaryDatabaseObject是NHibernate的一部分。如果只需要为数据库对象提供创建/删除脚本,则不必自己编写

我快速查看了Fluent NHibernate代码库,没有看到对IAuxiliaryDatabaseObject的任何直接支持。因此,这是一个公开配置对象并自己提供所有IauxiliaryDatabaseObject的问题。编写一些代码扫描映射程序集,查找实现IAuxiliaryDatabaseObject的类型,然后将它们传递给cfg.AddAuxiliaryDatabaseObject(obj),这不会太困难

您可以在NHibernate文档中找到有关辅助数据库对象的更多信息:


+1您最终找到了这样做的方法吗?我也遇到了同样的问题。您是否尝试过交换映射声明的顺序?(一点软糖,即使它有效!)UpTheCreek:正如本在下面所说的,我认为它不起作用。如果我有一个以上的多列索引,这种方法无论如何都会失败,因为它会迫使一个列成为所有索引中最顶端的索引列。谢谢。在这种情况下,您知道如何在配置中包含一些自定义(手写)模式吗?我更喜欢将所有与数据库创建相关的SQL放在一个地方。我想我可以在NHibernate构建模式的其余部分之后,执行普通SQL来添加索引。谢谢,这是一个不错的建议。但是,很少注意:a)我认为您的通用括号丢失了
,b)
createSQL
似乎返回了FluentHib中的字符串数组。1.1,c)您从未实际按索引编号对属性进行排序,d)
字段
列表本身不会在
sb.AppendLine
中正确呈现。我可以很容易地修复这些问题,但实际上我更喜欢在映射类中使用索引,而不是实际的实体,因此我可能会重写其中的一部分,将它们移动到那里。不过,你回答了我的问题,给了我一个好主意。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Text;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Mapping;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;

namespace FluentNHib
{

    public class Master
    {
        public int Id { get; set; }
    }

    public class Child
    {
        public int Id { get; set; }
        [MCIndex("A", 0)]
        public Master Master { get; set; }
        [MCIndex("A", 1)]
        public string Name { get; set; }
    }

    public class MCIndexAttribute : Attribute
    {
        public string indexName;
        public int indexOrder;

        public MCIndexAttribute(string indexName, int i)
        {
            this.indexName = indexName;
            this.indexOrder = i;
        }
    }

    public class MasterMap : ClassMap
    {
        public MasterMap()
        {
            Id(x => x.Id);
        }
    }

    public class ChildMap : ClassMap
    {
        public ChildMap()
        {
            Id(x => x.Id);
            References(x => x.Master).Index("A");
            Map(x => x.Name).Index("A");

        }
    }

    class MySchemaExport : SchemaExport
    {
        internal struct MCIndexField
        {
            internal int index;
            internal string Name;

        }

        internal class MCIndex
        {
            internal string IndexName;
            public readonly IList fields = new List();
            public string Table;

            public void AddField(string name, int indexOrder)
            {
                fields.Add(new MCIndexField {index = indexOrder, Name = name});
            }
        }

        private readonly Dictionary indexes = new Dictionary();

        MCIndex ByName(string name, string table)
        {
            MCIndex result;
            if (!indexes.TryGetValue(name, out result))
            {
                result = new MCIndex
                    {
                        IndexName = name
                    };
                indexes.Add(name, result);
            }
            return result;
        }

        public MySchemaExport(Configuration cfg) : base(cfg)
        {
            foreach (var type in typeof(ChildMap).Assembly.GetTypes())
            {
                foreach (var prop in type.GetProperties())
                {
                    var attr = prop.GetCustomAttributes(typeof (MCIndexAttribute), true);
                    if (attr.Length == 1)
                    {
                        var attribute = (MCIndexAttribute) attr[0];
                        ByName(attribute.indexName, type.Name).AddField(prop.Name, attribute.indexOrder);
                    }
                }
            }


            var createSqlProp = typeof(SchemaExport).GetField("createSQL", BindingFlags.NonPublic | BindingFlags.Instance);
            var wasSql = createSqlProp.GetValue(this);

            var sb = new StringBuilder();
            sb.AppendLine("");
            foreach (var mcIndex in indexes)
            {
                sb.AppendLine(string.Format("create index {0} on {1} ({2})", mcIndex.Value.IndexName, mcIndex.Value.Table, mcIndex.Value.fields));
            }
            createSqlProp.SetValue(this, wasSql + sb.ToString());
        }
    }

    class Program
    {

        private static void BuildSchema(Configuration config)
        {
            new MySchemaExport(config)
                .Create(s =>
                            {
                                Debug.WriteLine(s);
                            }, true);
        }

        const string fileName = "c:\\temp\\temp.fdb";

        private static string GetConnectionString()
        {
            const string userName = "sysdba";
            const string password = "masterkey";
            return String.Format("ServerType=1;User={0};Password={1};Dialect=3;Database={2}", userName, password, fileName);
        }

        private static FluentConfiguration Configurate()
        {
            var fbc = new FirebirdConfiguration();
            return Fluently.Configure()
            .Database(fbc.ShowSql().ConnectionString(GetConnectionString()))
                .Mappings(m => m.FluentMappings
                    .AddFromAssemblyOf()
                )
              .ExposeConfiguration(BuildSchema);
        }

        static void Main(string[] args)
        {
            FluentConfiguration fluentConfiguration = Configurate();

            Configuration cfg = fluentConfiguration.BuildConfiguration();
        }
    }
}
<hibernate-mapping xmlns="urn:nhiernate-mapping-2.2">
  <database-object>
     <create>VALID SQL</create>
     <drop>VALID SQL</create>
  </database-object>
</hibernate-mapping>
namespace NHibernate.Mapping {
    public interface IAuxiliaryDatabaseObject : IRelationalModel {
        void AddDialectScope(string dialectName);
        bool AppliesToDialect(Dialect dialect);
        void SetParameterValues(IDictionary<string, string> parameters);
    }
    public interface IRelationalModel {
        string SqlCreateString(Dialect dialect, IMapping p, string defaultCatalog, string defaultSchema);
        string SqlDropString(Dialect dialect, string defaultCatalog, string defaultSchema);
    }
}
var sqlCreate = "CREATION SCRIPT";
var sqlDrop = "DROP SCRIPT";    
cfg.AddAuxiliaryDatabaseObject(new SimpleAuxiliaryDatabaseObject(sqlCreate, sqlDrop));