Search code examples
c#nhibernatenhibernate-mapping

Can not use joined-subclass of xml mapping to extend the mappings build with NHibernate.Mapping.ByCode


I am refacting the mapping of NHibernate.AspNetCore.Identity to NHibernate.Mapping.ByCode , as descripted in the issue https://github.com/nhibernate/NHibernate.AspNetCore.Identity/issues/16 .

I have rewrite the orignal xml mapping of NHibernate.AspNetCore.Identity with ClassMapping<T>, the code looks like this:

public class IdentityRoleMappingPostgreSql : ClassMapping<IdentityRole> {

    public IdentityRoleMappingPostgreSql() {
        Schema("public");
        Table("aspnet_roles");
        Id(e => e.Id, id => {
            id.Column("id");
            id.Type(NHibernateUtil.String);
            id.Length(32);
            id.Generator(Generators.TriggerIdentity);
        });
        Property(e => e.Name, prop => {
            prop.Column("name");
            prop.Type(NHibernateUtil.String);
            prop.Length(64);
            prop.NotNullable(true);
            prop.Unique(true);
        });
        /* other property mappings ignored here .*/
    }

}

The full mapping code is here:

https://github.com/nhibernate/NHibernate.AspNetCore.Identity/tree/master/src/NHibernate.AspNetCore.Identity/Entities

Then I try to extend these mappings with joined-sublcass of xml mapping, like this:

<?xml version="1.0" encoding="UTF-8" ?>
<hibernate-mapping
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns="urn:nhibernate-mapping-2.2"
  namespace="WebTest.Entities" assembly="WebTest">

  <joined-subclass name="AppRole" schema="public" table="app_roles" extends="NHibernate.AspNetCore.Identity.IdentityRole, NHibernate.AspNetCore.Identity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
    <key column="id" />
    <property name="Description" column="description" type="string" length="256" />
  </joined-subclass>

</hibernate-mapping>

I got the following exception when setting up nhibernate:

NHibernate.MappingException : These classes referenced by 'extends' were not found:
FullName:NHibernate.AspNetCore.Identity.IdentityRole - Name:NHibernate.AspNetCore.Identity.IdentityRole, NHibernate.AspNetCore.Identity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
FullName:NHibernate.AspNetCore.Identity.IdentityUser - Name:NHibernate.AspNetCore.Identity.IdentityUser, NHibernate.AspNetCore.Identity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
   at NHibernate.Cfg.MappingsQueue.CheckNoUnavailableEntries()
   at NHibernate.Cfg.Configuration.SecondPassCompile()
   at NHibernate.Cfg.Configuration.BuildMappings()
   at UnitTest.IdentityTest._02_CanSetupMappingByXml()

Then I rewrite the xml mapping with JoinedSubclassMapping<AppRole> , which works , can build session factory and query without any exception.

public class AppRoleMapping : JoinedSubclassMapping<AppRole> {

    public AppRoleMapping() {
        ExplicitDeclarationsHolder
            .AddAsRootEntity(typeof(NHIdentityRole));
        Extends(typeof(NHIdentityRole));
        Schema("public");
        Table("app_roles");
        Key(k => k.Column("id"));
        Property(
            p => p.Description,
            maping => {
                maping.Column("description");
                maping.Type(NHibernateUtil.String);
                maping.Length(256);
            }
        );
    }

}

So the issue is:

  • when using JoinedSubclassMapping<T> to extend the mappings build with ClassMapping<T>, it works _01_CanExtendByCodeWithByCode;
  • when using joined-subclass of xml mapping to extend the mappings build with ClassMapping<T>, get an exception of NHibernate.MappingException : These classes referenced by 'extends' were not found_02_CanExtendByCodeWithXml;
  • when using joined-subclass xml mapping to extend class xml mapping, it works _03_CanExtendXmlByXml;
  • when using JoinedSubclassMapping<AppRole> to extend class mapping of xml, it works _04_CanExtendXmlByByCode;

The full test code is here: https://github.com/nhibernate/NHibernate.AspNetCore.Identity/blob/master/test/UnitTest/IdentityTest.cs

Maybe there something I do wrong, or some issues with nhibernate's mappings?


Solution

  • After debug and check the source code of NHibernate.Cfg.Configuration, there is an internal validation queue to process the mappings added by xml, but now way to skip it, so the simple work around is converting the HbmMapping to xml, then add the xml to configuration, let's double check it.

    var mapper = new ModelMapper();
    mapper.AddMapping<IdentityRoleMappingPostgreSql>();
    // add other mapping here.
    var mapping = mapper.CompileMappingForAllExplicitlyAddedEntities();
    // Use AddXml instead of AddMappings
    cfg.AddXml(mapping.AsString());