简体   繁体   English

NHibernate QueryOver基础查询子类

[英]NHibernate QueryOver query subclass from base

I have the following objects: 我有以下对象:

public abstract class Event {
    public virtual Guid Id { get; set; }
    public virtual string Description { get; set; }
}

public class TeamEvent : Event {
    public virtual Guid Id { get; set; }
    public virtual Team Team { get; set; }
}

public class PersonEvent : Event {
    public virtual Guid Id { get; set; }
    public virtual Person  Person { get; set; }
}

public class Team {
    public virtual Guid Id { get; set; }
    public virtual string Name { get; set; }
}

public class Person {
    public virtual Guid Id { get; set; }
    public virtual string Forename { get; set; }
    public virtual string Surname { get; set; }
}

And Mappings: 和映射:

    <discriminator column="Discriminator"
            not-null="true"
            type="System.String"/>

    <subclass
        name="TeamEvent"
        discriminator-value="TeamEvent">
        <many-to-one name="Team" column="TeamId"/>
    </subclass>

    <subclass
        name="PersonalEvent"
        discriminator-value="PersonalEvent">
        <many-to-one name="Person" column="PersonId"/>
    </subclass>
</class>
<class name="Person" table="Persons">
    <id name="Id">
        <generator class="assigned"/>
    </id>
    <property name="Forename"/>
    <property name="Surname"/>
</class>
<class name="Team" table="Teams">
    <id name="Id">
        <generator class="assigned"/>
    </id>
    <property name="TeamName"/>
</class>

What I'd like to do is a query that would get all events regardless of base type in one query to populate a DTO like: 我想做的是一个查询,该查询将获取所有事件,而与在一个查询中填充基类的基本类型无关:

public class EventDTO {
   public virtual Guid EventId { get; set; }
   public virtual string EventDescription { get; set; }
   public virtual Guid PersonId { get; set; }
   public virtual string PersonForename { get; set; }
   public virtual string PersonSurname { get; set; }
   public virtual Guid TeamId { get; set; }
   public virtual string TeamName { get; set; }
}

Where if it's a person event, the team fields are null and vice versa. 如果是个人事件,则团队字段为null,反之亦然。

In SQL I'd just do something like: 在SQL中,我只想做类似的事情:

Select * from Events
left join Team on Events.TeamId = Team.Id
left join Person on Events.Person = Person.Id

I can't do this in QueryOver as the Events c# object doesn't have properties for Team/Person. 我无法在QueryOver中执行此操作,因为Event c#对象没有Team / Person的属性。 I can do it like so: 我可以这样做:

var events = session.QueryOver<Event>
               .Where ( /* insert my restrictions */ )
               .Future<Event>();

var teamEvents = session.QueryOver<TeamEvent>
               .Where ( /* insert my restrictions */ )
               .Future<TeamEvent>();
var personEvents = session.QueryOver<PersonEvent>
               .Where ( /* insert my restrictions */ )
               .Future<PersonEvent>();

/* union the results in memory */

The amount of data coming back from these queries should be such that it's feasible to just union the results in memory. 从这些查询返回的数据量应该使得仅将结果合并到内存中是可行的。 My question is really is there a more elegant way of doing this? 我的问题是,确实有一种更优雅的方式吗? without doing three separate queries. 无需执行三个单独的查询。

I should point out this is just a quick example I've typed up to highlight my question so there may be some typos, etc in the above code samples. 我应该指出,这只是我输入的一个快速示例,以突出我的问题,因此上面的代码示例中可能会有一些错别字等。 In the real world problem there is other parts of the system depending on the mappings, so changing the schema/mappings/objects is not an option. 在实际问题中,系统的其他部分取决于映射,因此更改架构/映射/对象不是一种选择。

And whilst I'd prefer to use query over, I don't mind using criteria or hql if it's possible to do it in a simpler way there. 虽然我更喜欢使用查询,但我不介意使用条件或hql(如果可以的话)以一种更简单的方式进行查询。 Also this query will only return a max of 20 rows, of entities that are frequently accessed and thus stored in second level cache, so even an N + 1 isn't a major issue if it makes the code simple. 同样,此查询最多将返回最多20行,这些行经常被访问并因此存储在第二级缓存中,因此即使N + 1简化代码也不会成为主要问题。

I should also point out the reason the three queries one isn't so simple is because there needs to be 10 restrictions that need to be duplicated per query, and there are a couple of other subclasses of event. 我还应该指出三个查询不是那么简单的原因是,每个查询需要重复10个限制,并且还有其他两个事件子类。

Thanks for any help. 谢谢你的帮助。

When I hit problems like this I stop fighting NH and create a DB view. 当遇到此类问题时,我将停止与NH战斗并创建一个DB视图。 that I map as mutable=false . 我映射为mutable=false This way I don't get in a mess with paging or with my where clauses and merging multiple sets on client. 这样,我就不会陷入页面调度或where子句以及客户端上合并多个集合的麻烦。

Not sure if there is a nicer way (especially as you have related tables that you want to flatten) than what you have come up with. 不知道是否有比您想出的更好的方法(尤其是您有想要展平的相关表)。 As you have said that you don't have much data then merging on the client might be best. 正如您所说的那样,您没有太多数据,因此最好在客户端上进行合并。

You should be able to make it to work with HQL and writing a condition like : 您应该能够使其与HQL一起使用并编写类似以下的条件:

from Event where (..person event restrictions..) OR (..team event restrictions..)

since querying over abstract base class will force nHibernate to do the left joins and even though you specify derived properties they are accessible. 因为在抽象基类上进行查询将强制nHibernate进行左连接,即使您指定派生属性也可以访问它们。 So in simplified form , following query 所以以简化的形式,下面的查询

var personEvents = session
                    .CreateQuery("from Event where Person!=null")
                    .List<Event>();

will give you PersonEvent entities. 将为您提供PersonEvent实体。

So you should be able to construct simpler code BUT it really feels strange that you want to do load different subclasses in one query and process them at once etc. Future queries seem elegenant enough as they are focused on small (single) piece of responsibility - what would you do if there is a need for another event ? 因此,您应该能够构造更简单的代码,但确实确实很奇怪,您想在一个查询中加载不同的子类并立即处理它们,等等。将来的查询似乎足够精妙,因为它们专注于小的(单个)职责-如果需要其他活动该怎么办? It feels better to add another query rather than modify one master query again and again. 最好添加另一个查询,而不是一次又一次地修改一个主查询。

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

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