简体   繁体   中英

Mapping inheritance in NHibernate 3.3

I have the inheritance described below :

public abstract class BaseEntity<TId> {....}

public abstract class ModelEntity : BaseEntity<Int32>{....}

public abstract class AuditableEntity : ModelEntity,IAuditable{....}

public class ApplicationUser : AuditableEntity{....}

public class SuperUser : ApplicationUser

I am using NHibernate 3.3 and I want to Create the mappings for that inheritance

public abstract class ModelEntityMap<TEntity> : ClassMapping<TEntity>
        where TEntity : ModelEntity
{...}

public class AuditableEntityMap<TEntity> : ModelEntityMap<TEntity> where TEntity : AuditableEntity
{ ...}

public class ApplicationUserMap : AuditableEntityMap<ApplicationUser>
{...}

public class SuperUserMap : JoinedSubclassMapping<SuperUser>{...}

When the application starts and trys to set up the database it raises the following Exception : Ambiguous mapping for SuperUser More than one root entities was found BaseEntity / ApplicationUser

Possible solutions -Merge the mapping of root Entity in the one is representing the real root in the hierarchy -Inject a IModelInspector with a logic to discover the real root-entity.

I was using Fluent nhibernate with the same inheritance and worked fine with SuperUserMap defined as public class SuperUserMap : SubClassMap {...}

I am new to Nhibernate mapping by code and quite confused !!!

I believe there are two ways to solve this problem: a) Using the concept of discriminator that identifies the type of the class stored and thereby the right object is retrieved from the database, in this case your class is mapped to a table that has all the columns plus the discriminator columns. Not sure how this works with multi-level inheritance but this is something that you can google.

b) take a look at this post on how he deals with inheritance: http://fabiomaulo.blogspot.co.nz/2011/04/nhibernate-32-mapping-by-code_13.html you might get some idea to solve your issue.

You can influence the decision whether an entity is a root entity by overriding the IsRootEntity logic of the model mapper that you use to create mappings.

Here's an example that defines the default NHibernate mapping-by-code behaviour:

    var modelMapper = new ConventionModelMapper();
    modelMapper.IsRootEntity((type, declared) =>
    {
        if (declared) return true; // Type has already been declared as root entity
        return type.IsClass 
            && typeof(object) == type.BaseType 
            && modelMapper.ModelInspector.IsEntity(type);
    });

You will have to tweak this decision logic to exclude the BaseEntity class as possible root entity.

I had this error with NHibernate 4.1.1 (May 2017), so I'm answering with how I solved it for future reference

In my case, I copied an existing mapping of an inheriting class, and forgot to change the parent mapping class to ClassMapping and encountered the same error

In other words, in your mapping class, check the parent class, make sure it is ClassMapping or JoinedSubclassMapping if it's a child class

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM