如何更改多列索引中的列顺序?
即:
mapping.References(x => x.SomeReference).SetAttribute("index", "IX_index");
mapping.Map(x => x.SomeField).SetAttribute("index", "IX_index");
生成以下架构:
create index IX_index on ApplicantProgramDatas (SomeField, SomeReferenceId)
但我想得到:
create index IX_index on ApplicantProgramDatas (SomeReferenceId, SomeField)
答案 0 :(得分:4)
您可以使用< database-object>在NHibernate中定义索引。或IAuxiliaryDatabaseObject。
在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。 &LT;数据库对象&gt;可以在同一个hbm.xml文件中的类映射之前或之后进行,允许您将索引定义,触发器等保留在它们应用的对象中。
另一个选项是NHibernate.Mapping.IAuxiliaryDatabaseObject:
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);
}
}
鉴于您正在使用Fluent NHibernate,IAuxiliaryDatabaseObject可能会更适合您。只需在构建时公开您的配置,然后调用:
var sqlCreate = "CREATION SCRIPT";
var sqlDrop = "DROP SCRIPT";
cfg.AddAuxiliaryDatabaseObject(new SimpleAuxiliaryDatabaseObject(sqlCreate, sqlDrop));
N.B。 NHibernate.Mapping.SimpleAuxiliaryDatabaseObject是NHibernate的一部分。如果您只需要为数据库对象提供创建/删除脚本,则无需自己编写。
我快速查看了Fluent NHibernate代码库,但没有看到对IAuxiliaryDatabaseObject的任何直接支持。所以这是暴露配置对象并自己提供所有IAuxiliaryDatabaseObjects的问题。编写一些扫描遍历映射程序集的代码来查找实现IAuxiliaryDatabaseObject的类型然后对它们进行预处理以传递给cfg.AddAuxiliaryDatabaseObject(obj)并不会太困难。
您可以在NHibernate文档中找到有关辅助数据库对象的更多信息:
http://nhibernate.info/doc/nh/en/index.html#mapping-database-object
答案 1 :(得分:3)
我想这是不可能的。 '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);
因此,在多列索引中引用之前,您将始终拥有属性。
BTW没有一个ORM可以让你设置非平凡的索引选项,如聚类,过滤等。答案 2 :(得分:2)
我建议覆盖SchemaExport。通过反射有私有字段访问器,它需要完全信任模式。如果这种方法不适合您的需求,请考虑重写SchemaExport(相对较轻的类)
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();
}
}
}