C# 避免在双链接方案中指定键列
假设我有以下两个类:C# 避免在双链接方案中指定键列,c#,.net,nhibernate,fluent-nhibernate,C#,.net,Nhibernate,Fluent Nhibernate,假设我有以下两个类: public class User : Entity { public virtual IList<Item> Items { get; set; } } public class Item : Entity { public virtual User Owner { get; set; } } 公共类用户:实体 { 公共虚拟IList项{get;set;} } 公共类项:实体 { 公共虚拟用户所有者{get;set;} } 我创建了两个映
public class User : Entity
{
public virtual IList<Item> Items { get; set; }
}
public class Item : Entity
{
public virtual User Owner { get; set; }
}
公共类用户:实体
{
公共虚拟IList项{get;set;}
}
公共类项:实体
{
公共虚拟用户所有者{get;set;}
}
我创建了两个映射类:
public class UserMap : ClassMap<User>
{
public UserMap()
{
Id(x => x.Id);
HasMany(x => x.Items);
}
}
public class ItemMap : ClassMap<Item>
{
public ItemMap()
{
Id(x => x.Id);
References(x => x.Owner);
}
}
公共类用户映射:类映射
{
公共用户映射()
{
Id(x=>x.Id);
有许多(x=>x项);
}
}
公共类ItemMap:ClassMap
{
公共项目映射()
{
Id(x=>x.Id);
参考文献(x=>x.Owner);
}
}
这将产生一个表项
,其中有一列用户ID
和一列所有者ID
。当我在HasMany
映射上使用KeyColumn(“OwnerId”)
时,它只适用于OwnerId
列,但我希望避免这种情况。有没有办法告诉NHibernate使用由ItemMap
中的映射创建的列
避免显式指定列的原因:列名
OwnerId
将根据属性名称和一些规则自动生成。如果我更改了规则或属性名称,我需要记住也要更改KeyColumn
。因此,基本上,它不是重构保存。更新:修复错误
如果在地图中应用规则,则
public static void KeyColumnFromReference<TChild>(
this OneToManyPart<TChild> collectionmap, ClassMap<TChild> map, Expression<Func<TChild, object>> referenceprop)
{
string propertyname = GetPropertyName(referenceprop);
var column = ((IMappingProvider)map).GetClassMapping()
.References.First(m => m.Name == propertyname)
.Columns.First().Name;
collectionmap.KeyColumn(column);
}
public static void KeyColumnFromReference<T, TChild>(
this OneToManyPart<TChild> collectionmap, ClassMap<TChild> map)
{
var column = ((IMappingProvider)map).GetClassMapping()
.References.First(m => m.Type == typeof(TChild))
.Columns.First().Name;
collectionmap.KeyColumn(column);
}
public UserMap()
{
HasMany(x => x.Items)
.KeyColumnFromReference<User, Item>(new ItemMap());
// or
HasMany(x => x.Items)
.KeyColumnFromReference(new ItemMap(), u => u.Owner);
}
您可以将属性名称更改为User吗?公共虚拟用户用户{get;set;}。您还必须更改您的引用映射course@ColeW:嗯,将属性更改为User显然可以解决这个问题,但是属性的名称不如现在。我同意,但我认为没有干净的方法来处理您提出的其他问题。谢谢,看起来不错。但是,我想知道您是否确定此代码正在工作。在我看来,这就像是无休止的递归:在
UserMap
的ctor中,您创建了UserMap
的一个新实例。。。通过这个不是更好吗?谢谢你的代码-我刚刚测试了它。不幸的是,还有一个问题:它没有考虑外键格式化的约定。。。你能相应地更新你的代码吗?示例:我的约定是在属性名后面附加“Id”。您的代码附加了“_id”。如果您通过约定设置它,那么请参阅我的最后一句话。最好的选择是实现另一个相应更新的约定。代码仅适用于在类映射中指定列的情况。请使用IHasManyConvention
的实现更新您的答案?我不知道如何通过这种方式获得正确的列名。
class ForeignKeyConvention : IHasManyConvention
{
public void Apply(IOneToManyCollectionInstance instance)
{
// to force the compiler to take the Name property and not the Name method
string propertyName = ((ICollectionInspector)instance).Name;
// should be equal to the convention for the reference key column
instance.Key.Column(propertyName + instance.EntityType.Name + "id");
}
}