Fluent NHibernate:自定义ForeignKeyConvention不使用显式指定的表名

Fluent NHibernate:自定义ForeignKeyConvention不使用显式指定的表名,nhibernate,fluent-nhibernate,fluent-nhibernate-mapping,Nhibernate,Fluent Nhibernate,Fluent Nhibernate Mapping,编辑:对于tl;crowd博士,我的问题是:如何从ForeignKeyConvention内部访问映射,以确定给定类型映射到的表名 长版本: 我正在使用Fluent NHibernate来配置NHibernate,我有一个自定义外键约定,当我别名表和列时,它会失败 我的表使用一种约定,其中主键始终称为“PK”,外键为“FK”,后跟外键表的名称,例如“FKParent”。例如: CREATE TABLE OrderHeader ( PK INT IDENTITY(1,1) NOT NULL

编辑:对于tl;crowd博士,我的问题是:如何从ForeignKeyConvention内部访问映射,以确定给定类型映射到的表名

长版本:

我正在使用Fluent NHibernate来配置NHibernate,我有一个自定义外键约定,当我别名表和列时,它会失败

我的表使用一种约定,其中主键始终称为“PK”,外键为“FK”,后跟外键表的名称,例如“FKParent”。例如:

CREATE TABLE OrderHeader (
    PK INT IDENTITY(1,1) NOT NULL,
    ... 
)

CREATE TABLE OrderDetail (
    PK INT IDENTITY(1,1) NOT NULL, 
    FKOrderHeader INT NOT NULL,
    ...
)
为了实现这一点,我构建了一个定制的ForeignKeyConvention,如下所示:

public class AmberForeignKeyConvention : ForeignKeyConvention
{
    protected override string GetKeyName( Member member, Type type )
    {
        if ( member == null )
            return "FK" + type.Name;  // many-to-many, one-to-many, join

        return "FK" + member.Name; // many-to-one
    }
}
public class DetailMap : ClassMap<Detail>
{
    public DetailMap()
    {
        Table( "OrderDetail" );
        Id( o => o.PK );
        References( o => o.Order, "FKOrderHeader" );
        ...
    }
}
只要我的实体的名称与表的名称相同,这种方法就有效。但当他们不在的时候,它就坏了。例如,如果我想将OrderDetail表映射到名为Detail的类,我可以这样做:

public class AmberForeignKeyConvention : ForeignKeyConvention
{
    protected override string GetKeyName( Member member, Type type )
    {
        if ( member == null )
            return "FK" + type.Name;  // many-to-many, one-to-many, join

        return "FK" + member.Name; // many-to-one
    }
}
public class DetailMap : ClassMap<Detail>
{
    public DetailMap()
    {
        Table( "OrderDetail" );
        Id( o => o.PK );
        References( o => o.Order, "FKOrderHeader" );
        ...
    }
}
公共类详细信息映射:类映射
{
公共详细信息地图()
{
表(“订单详情”);
Id(o=>o.PK);
参考(o=>o.Order,“FKOrderHeader”);
...
}
}
映射用于加载单个实体,但当我尝试使用联接运行任何类型的复杂查询时,它都会失败,因为AmberForeignKeyConvention类对列的映射方式做出了错误的假设。也就是说,它假设外键应该是“FK”+type.Name,在本例中是Order,因此它调用外键“FKOrder”而不是“FKOrderHeader”


正如我上面所说的:我的问题是,如何从ForeignKeyConvention内部访问映射,以确定给定类型的映射表名(以及它们的映射列名)?的答案似乎暗示了正确的方向,但我不明白所涉及的类是如何协同工作的。当我浏览文档时,对于我所查找的类(例如)来说,它非常稀疏。

想法是加载映射

public class AmberForeignKeyConvention : ForeignKeyConvention
{
    private static IDictionary<Type, string> tablenames;

    static AmberForeignKeyConvention()
    {
        tablenames = Assembly.GetExecutingAssembly().GetTypes()
            .Where(t => typeof(IMappingProvider).IsAssignableFrom(t))
            .ToDictionary(
                t => t.BaseType.GetGenericArguments()[0], 
                t => ((IMappingProvider)Activator.CreateInstance(t)).GetClassMapping().TableName);
    }

    protected override string GetKeyName( Member member, Type type )
    {
        return "FK" + tablenames[type]; // many-to-one
    }
}
公共类AmberForeignKeyConvention:ForeignKeyConvention
{
私有静态索引表名;
静态AmberForeignKeyConvention()
{
tablenames=Assembly.GetExecutionGassembly().GetTypes()
.Where(t=>typeof(IMappingProvider).IsAssignableFrom(t))
.ToDictionary(
t=>t.BaseType.GetGenericArguments()[0],
t=>((IMappingProvider)Activator.CreateInstance(t)).GetClassMapping().TableName);
}
受保护的重写字符串GetKeyName(成员,类型)
{
返回“FK”+表名[type];//多对一
}
}

。它就像一个符咒。我确实不得不把
.AsDictionary
改成
.ToDictionary
,但除此之外,它是完美的。非常感谢!请注意使用此代码的人:我还遇到过一种情况,即我的表名周围有一个反勾号。我必须过滤字符串以删除反勾号,如下所示:
return“FK”+tablenames[type].Replace(“`,”)