Fluent NHibernate:自定义ForeignKeyConvention不使用显式指定的表名
编辑:对于tl;crowd博士,我的问题是:如何从ForeignKeyConvention内部访问映射,以确定给定类型映射到的表名 长版本: 我正在使用Fluent NHibernate来配置NHibernate,我有一个自定义外键约定,当我别名表和列时,它会失败 我的表使用一种约定,其中主键始终称为“PK”,外键为“FK”,后跟外键表的名称,例如“FKParent”。例如: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
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(“`,”)代码>