我们正在使用fluentnhibernate和自动化,我们有一个命名约定,所有列都是外键,列名将以“Key”结尾。所以我们有一个看起来像这样的约定:
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”结尾的外键?
答案 0 :(得分:1)
经过大量的摆弄和试用后错误(因此很想用反射来使用你的解决方案)我想出了以下内容:
此方法取决于约定的执行顺序。这种约定顺序通过严格的层次结构发生。在此示例中,首先,正在处理组件(IDynamicComponentConvention
)的约定,然后处理内部属性的约定,例如引用映射(IReferenceConvention
)。
严格的命令是我们进行罢工的地方:
我们在调用Apply(IDynamicComponentConvention instance)
时汇集了列的正确名称,并将其放入队列中。 请注意,使用Queue<T>
这是一个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!
}
}
答案 1 :(得分:0)
我已经找到了一种方法,使用反射来获取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;
}
}