NHibernate Free Automotive: How do I customize the subclass name and column name?

I think this must have been asked before, but I searched for an hour, but could not find the answer.

Let's say I have the following 2 models:

public class Organism { public virtual int Id { get; private set; } } public class Animal : Organism { } 

I want Fluent NHibernate to create the following tables for me:

 OrganismTable OrganismId AnimalTable AnimalId 

This can be easily achieved using manual matching:

 public class OrganismMappinig : ClassMap<Organism> { public OrganismMappinig() { Table("OrganismTable"); Id(x => x.Id).Column("OrganismId"); } } public class AnimalMapping : SubclassMap<Animal> { public AnimalMapping() { Table("AnimalTable"); KeyColumn("AnimalId"); } } 

But I can’t get the same result using a car. I tried to add the following conventions:

 public class TableNameConvension : IClassConvention, IClassConventionAcceptance { public void Apply(IClassInstance instance) { instance.Table(instance.EntityType.Name + "Table"); } public void Accept(IAcceptanceCriteria<IClassInspector> criteria) { criteria.Expect(x => x.TableName, Is.Not.Set); } } public class PrimaryKeyNameConvention : IIdConvention { public void Apply(IIdentityInstance instance) { instance.Column(instance.EntityType.Name + "Id"); } } 

He created these two tables:

 OrganismTable (correct) OrganismId (correct) Animal (wrong, should be "AnimalTable") Organism_id (wrong, should be "AnimalId") 

I also tried adding:

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

He created these two tables:

 OrganismTable (correct) OrganismId (correct) Animal (wrong, should be "AnimalTable") OrganismId (wrong, should be "AnimalId") 

I also tried adding:

 public class AnimalOverride : IAutoMappingOverride<Animal> { public void Override(AutoMapping<Animal> mapping) { mapping.Table("AnimalTable"); mapping.Id(x => x.Id).Column("AnimalId"); } } 

He created the following tables:

 OrganismTable (correct) OrganismId (correct) AnimalTable (correct) OrganismId (wrong, should be "AnimalId") 

This correctly set the table name for "AnimalTable" (but it requires too much manual input, it would be great if there was an agreement that could get the same result), but it was not possible to set the column name to "AnimalId".

Below is the rest of my code:

 class Program { static void Main(string[] args) { ISessionFactory sessionFactory = Fluently.Configure() .Database(MsSqlConfiguration .MsSql2008.ConnectionString(connectionString) .ShowSql()) .Mappings(m => m.AutoMappings.Add( AutoMap.Assemblies(typeof(Organism).Assembly) .Conventions.AddAssembly(typeof(Program).Assembly) .UseOverridesFromAssembly(typeof(Program).Assembly))) .ExposeConfiguration(BuildSchema) .BuildConfiguration() .BuildSessionFactory(); } static void BuildSchema(Configuration cfg) { new SchemaExport(cfg).Create(false, true); } } 

Any ideas? Thanks.

+4
source share
1 answer

When FluentNHibernate is automatic, it uses the table-per-specific class to display inheritance hierarchies. Because the body and animal are specific types, it generates two tables: OrganismTable and AnimalTable. OrganismTable retains all the properties common to all organisms. AnimalTable only saves properties added by the Animal subclass. PC on AnimalTable is also an FK for OrganismTable. Therefore, it depends on your FK convention. Note that PKNameConvention is called only for the body, not for animals. Like FKColumnNameConvention, only Animal is called. Because Animal FK is used only to bind the inheritance hierarchy, the property is null. Therefore, you get OrganismId as the name FK. To install this PK / FK, you need to use IJoinedSubclassConvention. (For completeness, I have included your TableNameConvention and PrimaryKeyNameConvention.)

 public class TableNameConvension : IClassConvention, IClassConventionAcceptance { public void Apply(IClassInstance instance) { instance.Table(instance.EntityType.Name + "Table"); } public void Accept(IAcceptanceCriteria<IClassInspector> criteria) { criteria.Expect(x => x.TableName, Is.Not.Set); } } public class PrimaryKeyNameConvention : IIdConvention { public void Apply(IIdentityInstance instance) { instance.Column(instance.EntityType.Name + "Id"); } } public class JoinedSubclassIdConvention : IJoinedSubclassConvention { public void Apply(IJoinedSubclassInstance instance) { instance.Table(instance.EntityType.Name + "Table"); instance.Key.Column(instance.EntityType.Name + "Id"); } } 

This generates:

 OrganismTable OrganismId AnimalTable AnimalId 

with FK from AnimalTable.AnimalId to OrganismTable.OrganismId.

Please note: the table-per-concrete class is not my preferred choice for matching inheritance due to the number of connections required when querying objects. Often, tables per subclass or table hierarchy per class are best suited. I will leave this as an exercise for the reader to explore the differences in NHibernate documentation in inheritance strategies .

+8
source

Source: https://habr.com/ru/post/1345476/


All Articles