FluentNHibernate: How to translate HasMany(x => x.

2019-06-01 17:53发布

问题:

Say I have these models:

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 Person { get; set; }
}

I want FluentNHibernate to create the following tables:

Person
    PersonId
Address
    AddressId
    PersonId

This can be easily achieved by using fluent mapping:

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

public class AddressMapping : ClassMap<Address>
{
    public AddressMapping()
    {
        Id(x => x.Id).Column("AddressId");
        References(x => x.Person).Column("PersonId");
    }
}

I want to get the same result by using auto mapping. I tried the following conventions:

class PrimaryKeyNameConvention : IIdConvention
{
    public void Apply(IIdentityInstance instance)
    {
        instance.Column(instance.EntityType.Name + "Id");
    }
}

class ReferenceNameConvention : IReferenceConvention
{
    public void Apply(IManyToOneInstance instance)
    {
        instance.Column(string.Format("{0}Id", instance.Name));
    }
}

But I sadly found it created the following tables:

Person
    PersonId
Address
    AddressId
    PersonId
    Person_id // this column should not exist

Below is the rest of my code:

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(ReferenceNameConvention)))

                //m.FluentMappings
                //    .Add(typeof (PersonMapping))
                //    .Add(typeof (AddressMapping))
    )
    .ExposeConfiguration(BuildSchema)
    .BuildConfiguration()
    .BuildSessionFactory();

Any ideas? Thanks.

回答1:

You need a foreign key convention:

public class SimpleForeignKeyConvention : ForeignKeyConvention
    {
        protected override string GetKeyName(Member property, Type type)
        {
            if(property == null)
                return type.Name + "Id";
            return property.Name + "Id";
        }
    }

Also, your reference convention should look more like:

instance.Column(instance.Property.Name + "Id");