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");
    }
}