简体   繁体   中英

NHibernate Mapping: Save hierarchy to single table without discriminator

I have a very extensible and modular application. I want to extend mapped Entites from other assemblies. Yet, I still need to operate on the base classes.

Example:

Parent class mapping in Assembly A:

    public class PersonMap : ClassMap<Person> 
    {
        public PersonMap()
        {
            Table("Persons");

            Id(x => x.Id).GeneratedBy.Assigned();
        }
}

Child class mapping in Assembly B:

public class EmployeeMap : SubclassMap<Employee>
{
    public EmployeeMap()
    {
        Table("Persons");
        Extends(typeof(Person));

        KeyColumn("Id");

        LazyLoad();

        HasMany<Assignments>(x => x.Assignments).KeyColumn("Id").Inverse().Cascade.AllDeleteOrphan().LazyLoad().NotFound.Ignore();
    }
}

Now whenever I create a Person in some code of Assembly A it is saved as Employee by NHibernate. And that leads to a class cast exception due to proxying whenever I save a Person and try to refresh it in Assembly A. Assembly A must not have a dependency on Assembly B.

I need to operate on the parent class in all methods of assembly A. The child class is only used in other assemblies.

How can I map something like that? How can I tell NHibernate to just save it as the parent class? I use SaveOrUpdate to persist the entities; How can I correctly extend entities and yet save them to the same table without discriminator? Can't NHibernate differentiate by object type? Is there a workaround?

I do not want to specify manual proxies as I'd have to create a proxy for every entity! I cannot use the visitor pattern due to dependency problems.

I need a way to extend a mapped entity in a different assembly without such problems! The database is legacy, I cannot change it. How would you work around the issue?

Your goal of mapping a hierarchy to a single table, without a discriminator, presents a conundrum. There must be SOMETHING in the data layer that gives the DAL a clue that a particular record is an Employee as opposed to just a Person. Since you aren't mapping any additional fields on the Persons table for an Employee, and not providing a discriminator, there's nothing about any single record of the Persons table that differentiates Persons from more-derived Employees.

Could you provide the code you're using to retrieve the Person records? In my experience, NHibernate queries virtually always require a domain type to hydrate. It may be that in this case, NHibernate is trying to create objects of the most derived type it knows, and because it can't tell the difference between a base Person and the more derived Employee, all Persons are Employees. You may try Linq, which forces strongly-typed object hydration, as opposed to HQL or other less strongly-referenced query.

Solved it by using a HasOne Mapping on the same Table and not using a subclass. This does not produce ideal code but is reather free of problems.

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