Skip to content

Mapping issues with SubclassAttribute #14

@beginor

Description

@beginor

I have found some issues when using SubclassAttribute with attribute mapping, for example, the base class is:

[Class(Schema = "public", Table="base_resources")]
[Discriminator(Column = "type")]
public class BaseResource {
    [Id(Name = nameof(Id), Column = "id", Type = "long", Generator = "trigger-identity")]
    public virtual long Id { get; set; }
    [Property(Name=nameof(Name), Column = "name", Type = "string", Length = 32, NotNull = true)]
    public virtual string Name { get; set; }
    [Property(Name=nameof(Type), Column = "type", Type = "string", Length = 64, NotNull = true, Insert = false, Update = false)]
    public virtual string Type { get; set; }
}

The generated xml mapping is correct :

<class table="base_resources" schema="public" name="NHibernate.Extensions.UnitTest.TestDb.BaseResource, NHibernate.Extensions.UnitTest">
  <id name="Id" column="id" type="long" generator="trigger-identity" />
  <discriminator column="type" />
  <property name="Name" type="string" column="name" length="32" not-null="true" />
  <property name="Type" type="string" column="type" length="64" not-null="true" update="false" insert="false" />
 </class>

And I have a sub class which is:

[Subclass(DiscriminatorValue = "data_api", ExtendsType = typeof(BaseResource), Lazy = true)]
public class DataApi : BaseResource {
    [Join(Schema = "public", Table = "data_apis", Fetch = JoinFetch.Select)]
    [Key(Column = "id")]
    [Property(Name = nameof(Statement), Column = "statement", Length = 128, NotNull = true)]
    public virtual string Statement { get; set; }
    [Property(Name = nameof(Parameters), Column = "parameters", Length = 128, NotNull = true)]
    public virtual string Parameters { get; set; }
}

This looks correct, but the xml mapping generated is not correct:

<subclass discriminator-value="data_api" extends="NHibernate.Extensions.UnitTest.TestDb.BaseResource, NHibernate.Extensions.UnitTest" lazy="true" name="NHibernate.Extensions.UnitTest.TestDb.DataApi, NHibernate.Extensions.UnitTest">
  <property name="Parameters" column="parameters" length="128" not-null="true" />
  <join table="data_apis" schema="public" fetch="select">
    <key column="id" />
    <property name="Statement" column="statement" length="128" not-null="true" />
  </join>
</subclass>

The property element for Parameters goes out of the join element, which should be inside the join element.

Then I change the code for DataApi, move all of the PropertyAttribute to one property, like this:

[Subclass(DiscriminatorValue = "data_apis", ExtendsType = typeof(BaseResource), Lazy = true)]
public class DataApi : BaseResource {
    [Join(Schema = "public", Table = "data_apis", Fetch = JoinFetch.Select)]
    [Key(Column = "id")]
    [Property(Name = nameof(Statement), Column = "statement", Length = 128, NotNull = true)]
    [Property(Name = nameof(Parameters), Column = "parameters", Length = 128, NotNull = true)]
    public virtual string Statement { get; set; }
    public virtual string Parameters { get; set; }
}

Then the xml mapping generated is corrected now, looks like:

<subclass discriminator-value="data_api" extends="NHibernate.Extensions.UnitTest.TestDb.BaseResource, NHibernate.Extensions.UnitTest" lazy="true" name="NHibernate.Extensions.UnitTest.TestDb.DataApi, NHibernate.Extensions.UnitTest">
  <join table="data_apis" schema="public" fetch="select">
    <key column="id" />
    <property name="Parameters" column="parameters" length="128" not-null="true" />
    <property name="Statement" column="statement" length="128" not-null="true" />
  </join>
</subclass>

But is the sub class DataApi has a many-to-one mapping like this:

[Subclass(DiscriminatorValue = "data_api", ExtendsType = typeof(BaseResource), Lazy = true)]
public class DataApi : BaseResource {
    [Join(Schema = "public", Table = "data_apis", Fetch = JoinFetch.Select)]
    [Key(Column = "id")]
    [ManyToOne(Name = "DataSource", Column = "data_source_id", ClassType = typeof(DataSource), NotFound = NotFoundMode.Ignore, Lazy = Laziness.Proxy, Fetch = FetchMode.Select)]
    [Property(Name = nameof(Statement), Column = "statement", Length = 128, NotNull = true)]
    [Property(Name = nameof(Parameters), Column = "parameters", Length = 128, NotNull = true)]
    public virtual DataSource DataSource { get; set; }
    public virtual string Statement { get; set; }
    public virtual string Parameters { get; set; }
}

The xml mapping generated is not correct again, like this:

<subclass discriminator-value="data_api" extends="NHibernate.Extensions.UnitTest.TestDb.BaseResource, NHibernate.Extensions.UnitTest" lazy="true" name="NHibernate.Extensions.UnitTest.TestDb.DataApi, NHibernate.Extensions.UnitTest">
  <join table="data_apis" schema="public" fetch="select">
    <key column="id" />
    <many-to-one name="DataSource" class="Beginor.GisHub.DataServices.Data.DataSource, Beginor.GisHub.DataServices" column="data_source_id" fetch="select" lazy="proxy" not-found="ignore" />
  </join>
</subclass>

There is only one many-to-one element , other properties is not generated.

But if I move the ManyToOne after Property, like this:

[Subclass(DiscriminatorValue = "data_api", ExtendsType = typeof(BaseResource), Lazy = true)]
public class DataApi : BaseResource {
    public virtual DataSource DataSource { get; set; }
    [Join(Schema = "public", Table = "data_apis", Fetch = JoinFetch.Select)]
    [Key(Column = "id")]
    [Property(Name = nameof(Statement), Column = "statement", Length = 128, NotNull = true)]
    [Property(Name = nameof(Parameters), Column = "parameters", Length = 128, NotNull = true)]
    [ManyToOne(Name = "DataSource", Column = "data_source_id", ClassType = typeof(DataSource), NotFound = NotFoundMode.Ignore, Lazy = Laziness.Proxy, Fetch = FetchMode.Select)]
    public virtual string Statement { get; set; }
    public virtual string Parameters { get; set; }
}

Then the xml mapping generated is correct again, like this:

<subclass discriminator-value="data_api" extends="NHibernate.Extensions.UnitTest.TestDb.BaseResource, NHibernate.Extensions.UnitTest" lazy="true" name="NHibernate.Extensions.UnitTest.TestDb.DataApi, NHibernate.Extensions.UnitTest">
  <join table="data_apis" schema="public" fetch="select">
    <key column="id" />
    <property name="Parameters" column="parameters" length="128" not-null="true" />
    <property name="Statement" column="statement" length="128" not-null="true" />
    <many-to-one name="DataSource" class="Beginor.GisHub.DataServices.Data.DataSource, Beginor.GisHub.DataServices" column="data_source_id" fetch="select" lazy="proxy" not-found="ignore" />
  </join>
</subclass>

I think that's very strange behavior,is there any who can tell me the magic?

And I think SubclassAttribute should be used the same way as ClassAttribute, like this:

[Subclass(DiscriminatorValue = "data_api", ExtendsType = typeof(BaseResource), Lazy = true)]
[Join(Schema = "public", Table = "data_apis", Fetch = JoinFetch.Select)]
[Key(Column = "id")]
public class DataApi : BaseResource {
    [ManyToOne(Name = "DataSource", Column = "data_source_id", ClassType = typeof(DataSource), NotFound = NotFoundMode.Ignore, Lazy = Laziness.Proxy, Fetch = FetchMode.Select)]
    public virtual DataSource DataSource { get; set; }
    [Property(Name = nameof(Statement), Column = "statement", Length = 128, NotNull = true)]
    public virtual string Statement { get; set; }
    [Property(Name = nameof(Parameters), Column = "parameters", Length = 128, NotNull = true)]
    public virtual string Parameters { get; set; }
}

Is anyone who can improve it?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions