Fluent nhibernate 如何重命名作为外键的组件列?
我们使用fluentnhibernate进行自动映射,我们有一个命名约定,即所有列都是外键,它们的列名将以“Key”结尾。所以我们有一个这样的惯例:Fluent nhibernate 如何重命名作为外键的组件列?,fluent-nhibernate,components,automapping,Fluent Nhibernate,Components,Automapping,我们使用fluentnhibernate进行自动映射,我们有一个命名约定,即所有列都是外键,它们的列名将以“Key”结尾。所以我们有一个这样的惯例: public class ForeignKeyColumnNameConvention : IReferenceConvention { public void Apply ( IManyToOneInstance instance ) { // name the key field string p
public class ForeignKeyColumnNameConvention : IReferenceConvention
{
public void Apply ( IManyToOneInstance instance )
{
// name the key field
string propertyName = instance.Property.Name;
instance.Column ( propertyName + "Key" );
}
}
这非常有效,直到我们创建了一个组件,其中一个值是外键。通过在此处重命名该列,它将覆盖给定给组件列的默认名称,其中包括AutomappingConfiguration中定义的ComponentPrefix。有没有办法让我在这个约定中得到ComponentPrefix?或者是否有其他方法可以获取属性为外键的组件的列名,以单词“key”结尾?我已经找到了一种方法,使用反射来获取IComponentInstance公开的IManyToOneInspector的底层映射,但希望有更好的方法来实现这一点 下面是我如何实现这一点的一些示例代码:
#region IConvention<IComponentInspector, IComponentInstance> Members
public void Apply(IComponentInstance instance)
{
foreach (var manyToOneInspector in instance.References)
{
var referenceName = string.Format("{0}_{1}_{2}{3}", instance.EntityType.Name, manyToOneInspector.Property.PropertyType.Name, _autoMappingConfiguration.GetComponentColumnPrefix(instance.Property), manyToOneInspector.Property.Name);
if(manyToOneInspector.Property.PropertyType.IsSubclassOf(typeof(LookupBase)))
{
referenceName += "Lkp";
}
manyToOneInspector.Index ( string.Format ( "{0}_FK_IDX", referenceName ) );
}
}
#endregion
public static class ManyToOneInspectorExtensions
{
public static ManyToOneMapping GetMapping(this IManyToOneInspector manyToOneInspector)
{
var fieldInfo = manyToOneInspector.GetType ().GetField( "mapping", BindingFlags.NonPublic | BindingFlags.Instance );
if (fieldInfo != null)
{
var manyToOneMapping = fieldInfo.GetValue( manyToOneInspector ) as ManyToOneMapping;
return manyToOneMapping;
}
return null;
}
public static void Index(this IManyToOneInspector manyToOneInspector, string indexName)
{
var mapping = manyToOneInspector.GetMapping ();
mapping.Index ( indexName );
}
public static void Column(this IManyToOneInspector manyToOneInspector, string columnName)
{
var mapping = manyToOneInspector.GetMapping ();
mapping.Column ( columnName );
}
public static void ForeignKey(this IManyToOneInspector manyToOneInspector, string foreignKeyName)
{
var mapping = manyToOneInspector.GetMapping();
mapping.ForeignKey ( foreignKeyName );
}
}
public static class ManyToOneMappingExtensions
{
public static void Index (this ManyToOneMapping manyToOneMapping, string indexName)
{
if (manyToOneMapping.Columns.First().IsSpecified("Index"))
return;
foreach (var column in manyToOneMapping.Columns)
{
column.Index = indexName;
}
}
public static void Column(this ManyToOneMapping manyToOneMapping, string columnName)
{
if (manyToOneMapping.Columns.UserDefined.Count() > 0)
return;
var originalColumn = manyToOneMapping.Columns.FirstOrDefault();
var column = originalColumn == null ? new ColumnMapping() : originalColumn.Clone();
column.Name = columnName;
manyToOneMapping.ClearColumns();
manyToOneMapping.AddColumn(column);
}
public static void ForeignKey(this ManyToOneMapping manyToOneMapping, string foreignKeyName)
{
if (!manyToOneMapping.IsSpecified("ForeignKey"))
manyToOneMapping.ForeignKey = foreignKeyName;
}
}
#地区IConvention成员
public void Apply(IComponentInstance实例)
{
foreach(instance.References中的var manyToOneInspector)
{
var referenceName=string.Format(“{0}{1}{2}{3}”,instance.EntityType.Name,manyToOneInspector.Property.PropertyType.Name,_autoMappingConfiguration.getComponentColumnProfix(instance.Property),manyToOneInspector.Property.Name);
if(manyToneInspector.Property.PropertyType.IsSubclassOf(typeof(LookupBase)))
{
referenceName+=“Lkp”;
}
manyToOneInspector.Index(string.Format(“{0}\u FK\u IDX”,referenceName));
}
}
#端区
公共静态类ManyToneInspectorExtensions
{
公共静态ManyToOneMapping GetMapping(此IManyToOneInspector manyToOneInspector)
{
var fieldInfo=manyToOneInspector.GetType().GetField(“映射”,BindingFlags.NonPublic | BindingFlags.Instance);
如果(fieldInfo!=null)
{
var manyToOneMapping=fieldInfo.GetValue(manyToOneInspector)作为manyToOneMapping;
返回多通映射;
}
返回null;
}
公共静态无效索引(此IManyToOneInspector MANYTONEINSPECTOR,字符串indexName)
{
var-mapping=manyToOneInspector.GetMapping();
mapping.Index(indexName);
}
公共静态无效列(此IManyToOneInspector MANYTONEINSPECTOR,字符串列名称)
{
var-mapping=manyToOneInspector.GetMapping();
mapping.Column(columnName);
}
公共静态void ForeignKey(此IManyToOneInspector manyToOneInspector,字符串foreignKeyName)
{
var-mapping=manyToOneInspector.GetMapping();
mapping.ForeignKey(foreignKeyName);
}
}
公共静态类ManyToneMappingExtensions
{
公共静态void索引(此ManyToOneMapping ManyToOneMapping,字符串indexName)
{
if(manyToneMapping.Columns.First().IsSpecified(“索引”))
返回;
foreach(manyToOneMapping.Columns中的var列)
{
column.Index=indexName;
}
}
公共静态void列(此ManyToOneMapping ManyToOneMapping,字符串columnName)
{
if(manyToneMapping.Columns.UserDefined.Count()>0)
返回;
var originalColumn=manyToneMapping.Columns.FirstOrDefault();
var column=originalColumn==null?新ColumnMapping():originalColumn.Clone();
column.Name=columnName;
manyToOneMapping.ClearColumns();
manyToOneMapping.AddColumn(column);
}
公共静态void ForeignKey(此ManyToOneMapping ManyToOneMapping,字符串foreignKeyName)
{
如果(!manyToneMapping.IsSpecified(“ForeignKey”))
manyToOneMapping.ForeignKey=foreignKeyName;
}
}
经过大量的修改和尝试与错误(因此,我很想使用您的解决方案进行反射),我得出了以下结论:
此方法取决于约定的执行顺序。这种约定顺序是通过严格的层次结构实现的。在本例中,首先处理组件的约定(IDynamicComponentConvention
),然后处理内部属性的约定,例如引用映射(IReferenceConvention
)
严格的命令是我们罢工的地方:
Apply(IDynamicComponentConvention实例)
时,我们将列的正确名称组合在一起,并将其放入队列中。请注意,使用了一个队列
,它是FIFO(先进先出)收集类型,因此它可以正确地保持顺序Apply(IManyToOneInstanceinstance)
。我们检查队列中是否有东西。如果有,我们将其从队列中取出,并将其设置为列名。请注意,您不应该使用Peek()
而不是Dequeue()
,因为它不会从队列中删除对象public sealed class CustomNamingConvention : IDynamicComponentConvention, IReferenceConvention {
private static Queue<string> ColumnNames = new Queue<string>();
public void Apply(IDynamicComponentInstance instance) {
foreach (var referenceInspector in instance.References) {
// All the information we need is right here
// But only to inspect, no editing yet :(
// Don't worry, just assemble the name and enqueue it
var name = string.Format("{0}_{1}",
instance.Name,
referenceInspector.Columns.Single().Name);
ColumnNames.Enqueue(name);
}
}
public void Apply(IManyToOneInstance instance) {
if (!ColumnNames.Any())
// Nothing in the queue? Just return then (^_^)
return;
// Set the retrieved string as the column name
var columnName = ColumnNames.Dequeue();
instance.Column(columnName);
// Pick a beer and celebrate the correct naming!
}
}
公共密封类CustomNamingConvention:IDynamicComponentConvention,IReferenceConvention{
私有静态队列ColumnNames=新队列();
public void Apply(IDynamicComponentInstance实例){
foreach(instance.References中的var referenceInspector){
//我们需要的所有信息都在这里
//但仅用于检查,尚未编辑:(
//别担心,只需将名称组合起来并将其排队即可
var name=string.Format(“{0}{1}”,
实例.名称,
referenceInspector.Columns.Single().Name);
ColumnNames.Enqueue(名称);
}
}
public void Apply(IManyToOneInstance实例){
如果(!ColumnNames.Any())
//队列中没有任何内容?然后返回(^ ^)
返回;
//将检索到的字符串设置为