简体   繁体   English

NHibernate映射:将层次结构保存到单个表而不带鉴别器

[英]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. 我想从其他程序集扩展映射的Entites。 Yet, I still need to operate on the base classes. 然而,我仍然需要对基类进行操作。

Example: 例:

Parent class mapping in Assembly A: 程序集A中的父类映射:

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

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

Child class mapping in Assembly B: 程序集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. 现在每当我在Assembly A的一些代码中创建Person时,它就被NHibernate保存为Employee。 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. 每当我保存一个Person并尝试在Assembly A中刷新它时,由于代理会导致类转换异常。程序集A必须不依赖于程序集B.

I need to operate on the parent class in all methods of assembly A. The child class is only used in other assemblies. 我需要在程序集A的所有方法中对父类进行操作。子类仅用于其他程序集。

How can I map something like that? 我该如何映射这样的东西? How can I tell NHibernate to just save it as the parent class? 我如何告诉NHibernate将它保存为父类? I use SaveOrUpdate to persist the entities; 我使用SaveOrUpdate来持久保存实体; How can I correctly extend entities and yet save them to the same table without discriminator? 如何正确扩展实体,然后将它们保存到同一个表中而没有鉴别器? Can't NHibernate differentiate by object type? NHibernate不能按对象类型区分吗? 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. 数据层中必须有SOMETHING,它为DAL提供了一条特定记录是员工而不仅仅是人员的线索。 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. 由于您没有在员工的Persons表上映射任何其他字段,并且没有提供鉴别器,因此没有任何关于Persons表的单个记录可以区分人员和派生更多的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. 根据我的经验,NHibernate查询几乎总是需要域类型来保持水合。 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. 在这种情况下,NHibernate可能会尝试创建它知道的派生类型最多的对象,并且由于它无法区分基本Person和派生的Employee之间的区别,因此所有人员都是Employees。 You may try Linq, which forces strongly-typed object hydration, as opposed to HQL or other less strongly-referenced query. 您可以尝试Linq,它强制强类型对象水合,而不是HQL或其他不太强烈引用的查询。

Solved it by using a HasOne Mapping on the same Table and not using a subclass. 通过在同一个表上使用HasOne映射而不使用子类来解决它。 This does not produce ideal code but is reather free of problems. 这不会产生理想的代码,但是没有问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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