Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
beginor opened this issue Jan 18, 2020 · 5 comments

Comments

@beginor
Copy link
Member

beginor commented Jan 18, 2020

I am refacting the mapping of NHibernate.AspNetCore.Identity to NHibernate.Mapping.ByCode , as descripted in the issue nhibernate/NHibernate.AspNetCore.Identity#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?

@beginor
Copy link
Member Author

beginor commented Jan 21, 2020

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 no 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());

@fredericDelaporte
Copy link
Member

I do not know if mixing hbm and By-Code mappings is an "accidental" feature or if it is supposed to work flawlessly in any cases. So I do not really know if the trouble your report should be qualified as a bug or as a feature request.

For now I settle on feature request.

@beginor
Copy link
Member Author

beginor commented Jan 27, 2020

I think it should be a feature too. Maybe we should provide an optional parameter for mapping by xml, let users to specify explicited root entity, provide similar function like the ExplicitDeclarationsHolder.AddAsRootEntity() method in mapping by code.

@craigfowler
Copy link

I've just run into this and I can provide a very good (at least IMO) reason why this scenario should be supported.

That's because of issue #1277, for which the workaround is essentially "Use an .hbm.xml mapping instead of mapping-by-code for the affected class". This has meant that I have needed to mix-and-match MbC class mappings and a single XML embedded resource mapping (which just happened to be for a <subclass />) in the same environment.

FWIW, the workaround @beginor described (convert the MbC mappings to XML & import as XML, then add .hbm.xml mappings) did work for me.

@craigfowler
Copy link

I have noticed that the workaround: using MBC, then convert those mappings to XML and add them that way, is somewhat less viable from NHibernate 5.4.1 onward. That's if those mappings contain any one-to-one relationships, because of a new crash bug adding the mappings. See #3607 for more information.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants