NHibernate and inheritance creating unexpected double request behavior?

I am using FluentNHibernate. I do not use auto-mapping. I have a base class that is a subclass. When I request the base class, it makes an additional request to the subclass. Here's a (far-fetched) example of what I'm doing:

public class Foo { int Id; string SomeValue; } 

I create another class that represents the audit record of the first, and I inherit it:

 public class FooAudit : Foo { DateTime DateModified; } 

I create separate mappings for each that go to their own tables:

 public class FooMap : ClassMap<Foo> { public FooAuditMap() { Table("Foo"); Id(x => x.Id).Column("FOO_ID"); Map(x => x.SomeValue).Column("SOME_VALUE"); } } public class FooAuditMap : ClassMap<FooAuditMap> { public FooAuditMap() { Table("FooAudit"); CompositeId() .KeyProperty(x => x.DateModified, c => c.ColumnName("AUDIT_DATE")); .KeyProperty(x => x.Id, c => c.ColumnName("FOO_ID")); Map(x => x.SomeValue).Column("SOME_VALUE"); } } 

I am running a query against Foo:

 public virtual IEnumerable<Foo> List() { using (var session = SessionFactory.OpenSession()) { return session.CreateCriteria<Foo>().List<Foo>(); } } 

which then hits the DB twice, once to execute this query against Foo and again in FooAudit.

Why is he making two requests? I generated HBM files and absolutely nothing binds these classes.

EDIT: for completeness, it looks like a bootstrap script.

 public static ISessionFactory CreateSessionFactory() { return Fluently .Configure() .Database ( FluentNHibernate.Cfg .Db.MsSqlConfiguration.MsSql2005 .ConnectionString(GetConnectionString()) ) .Mappings(m => m .FluentMappings.AddFromAssemblyOf<Foo>() .Conventions.Add(typeof(EnumConvention))) .BuildSessionFactory(); } 
+4
source share
2 answers

What you see is the expected behavior.

A base class query also queries inherited classes.

If there is an explicit NHibernate mapping for this (subclass, merged subclass, etc.), this will be just one request. Otherwise, he considered an implicit polymorphic definition, and two queries are issued to return the results from all of them.

I believe (from the docs I haven't tried) that you can avoid this by matching the class with polymorphism="explicit" . I do not know if Fluent supports it.

+4
source

Try:

 public class FooAuditMap : SubclassMap<FooAudit> { public FooAuditMap() { Table("FooAudit"); CompositeId() .KeyProperty(x => x.DateModified, c => c.ColumnName("AUDIT_DATE")); .KeyProperty(x => x.Id, c => c.ColumnName("FOO_ID")); Map(x => x.SomeValue).Column("SOME_VALUE"); } } 

You still have a problem because the identifier for Foo and FooAudit is different. If FooAudit is a subclass of Foo, it must have the same identifier as that stored in the Foo table.

Update based on OP comment: you probably have an inheritance chain in the domain model without expressing it in NHibnerate. Just change the FooAuditMap to inherit the ClassMap<FooAudit> . However, your query for an object of type Foo will not contain any FooAudit types because NH is not aware of the relationship.

But I think you have a one-to-many relationship - Foo has a collection of FooAudits - and you should map it that way.

Update 2: It seems that my previous statement "However, your request for an object of type Foo will not contain any FooAudit types because NH is not aware of the relationship." wrong. There is a way to return only the base class, limiting the results using the property of a special class , but this is not a great solution.

I think it would be better for you to get rid of inheritance and either both classes implement the interface or display common properties as a component.

0
source

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


All Articles