FluentNHibernate:使用属性和约定自动映射OneToMany关系

FluentNHibernate:使用属性和约定自动映射OneToMany关系,nhibernate,fluent-nhibernate,automapping,Nhibernate,Fluent Nhibernate,Automapping,这与我之前的问题非常相似: 假设我有这些模型: public class Person { public virtual int Id { get; private set; } public virtual ICollection<Address> Addresses { get; private set; } } public class Address { public virtual int Id { get; private set; }

这与我之前的问题非常相似:


假设我有这些模型:

public class Person
{
    public virtual int Id { get; private set; }
    public virtual ICollection<Address> Addresses { get; private set; }
}

public class Address
{
    public virtual int Id { get; private set; }
    public virtual Person Owner { get; set; }
}
这可以通过使用fluent映射轻松实现:

public class PersonMapping : ClassMap<Person>
{
    public PersonMapping()
    {
        Id(x => x.Id).Column("PersonId");
        HasMany(x => x.Addresses).KeyColumn("OwnerId");
    }
}

public class AddressMapping : ClassMap<Address>
{
    public AddressMapping()
    {
        Id(x => x.Id).Column("AddressId");
        References(x => x.Person).Column("OwnerId");
    }
}
但它创建了以下表格:

Person
    PersonId
Address
    AddressId
    OwnerId
Person
    PersonId
Address
    AddressId
    OwnerId
    PersonId // this column should not exist
因此,我添加了一个AutomappingGoverride:

public class PersonMappingOverride : IAutoMappingOverride<Person>
{
    public void Override(AutoMapping<Person> mapping)
    {
        mapping.HasMany(x => x.Addresses).KeyColumn("OwnerId");
    }
}
下面是我的代码的其余部分:

ISessionFactory sessionFactory = Fluently.Configure()
    .Database(MsSqlConfiguration.MsSql2008.ConnectionString(connectionString))
    .Mappings(m =>
                m.AutoMappings.Add(AutoMap.Assemblies(typeof(Person).Assembly)
                    .Conventions.Add(typeof(PrimaryKeyNameConvention))
                          .Conventions.Add(typeof(PrimaryKeyNameConvention))
                          .Conventions.Add(typeof(ReferenceNameConvention))
                          .Conventions.Add(typeof(SimpleForeignKeyConvention))
                          .Conventions.Add(typeof(KeyColumnConvention)))

                //m.FluentMappings
                //    .Add(typeof (PersonMapping))
                //    .Add(typeof (AddressMapping))
    )
    .ExposeConfiguration(BuildSchema)
    .BuildConfiguration()
    .BuildSessionFactory();
有什么想法吗?谢谢


更新:


测试项目可以从下载。

我已经使用FHN的自动映射功能测试了您的类,它不会在地址表上创建第二个PersonId。
我正在使用FHN v1.2.0.721,来自。。。学习NHibernate真是一次令人毛骨悚然的经历

无论如何,我想我终于找到了解决这个问题的方法:只要删除
SimpleForeignKeyConvention
,一切都会正常工作

似乎
simpleForeiveKeyConvention
ReferenceKeyConvention
KeyColumnConvention
冲突。它的优先级高于
KeyColumnConvention
,但低于
ReferenceKeyConvention

public class SimpleForeignKeyConvention : ForeignKeyConvention
{
    protected override string GetKeyName(Member property, Type type)
    {
        if(property == null)
            // This line will disable `KeyColumnConvention`
            return type.Name + "Id";

        // This line has no effect when `ReferenceKeyConvention` is enabled.
        return property.Name + "Id";
    }
}

感谢您的测试!您是否在配置中包含
PersonMappingOverride
?如果是,则不会在
地址
表上创建第二个
PersonId
。但它应该被排除在配置之外,因为我希望通过使用
KeyColumnAttribute
&
KeyColumnConvention
获得相同的结果。我已经用我的测试项目的下载链接更新了我的问题,它应该会重现这个问题。现在你已经更改了属性的名称,对吗?(为了证明…)所以请阅读这个类似的帖子(为了避免有两个不同的外键列…):注意接受答案,让其他人知道这是解决问题的方法problem@Firo:我收到一条信息“你可以在x小时内接受你自己的答案”(目前,x=16)。我明天再试一次。
Person
    PersonId
Address
    AddressId
    OwnerId
    PersonId // this column should not exist
ISessionFactory sessionFactory = Fluently.Configure()
    .Database(MsSqlConfiguration.MsSql2008.ConnectionString(connectionString))
    .Mappings(m =>
                m.AutoMappings.Add(AutoMap.Assemblies(typeof(Person).Assembly)
                    .Conventions.Add(typeof(PrimaryKeyNameConvention))
                          .Conventions.Add(typeof(PrimaryKeyNameConvention))
                          .Conventions.Add(typeof(ReferenceNameConvention))
                          .Conventions.Add(typeof(SimpleForeignKeyConvention))
                          .Conventions.Add(typeof(KeyColumnConvention)))

                //m.FluentMappings
                //    .Add(typeof (PersonMapping))
                //    .Add(typeof (AddressMapping))
    )
    .ExposeConfiguration(BuildSchema)
    .BuildConfiguration()
    .BuildSessionFactory();
public class SimpleForeignKeyConvention : ForeignKeyConvention
{
    protected override string GetKeyName(Member property, Type type)
    {
        if(property == null)
            // This line will disable `KeyColumnConvention`
            return type.Name + "Id";

        // This line has no effect when `ReferenceKeyConvention` is enabled.
        return property.Name + "Id";
    }
}