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