【问题标题】:NHibernate QueryOver - collection with too many resultsNHibernate QueryOver - 有太多结果的集合
【发布时间】:2013-09-18 01:30:21
【问题描述】:

尊敬的 NHibernate 用户,

我已经尝试、阅读和诸如此类的 2 天了,但仍然无法弄清楚这一点,即使我认为使用 QueryOver API 是一件容易的事。

这是我的两个实体:

ATTRIBUTE
---------------------------
public int Id { get; set; }
public int LanguageId { get; set; }
public string Title { get; set; }
public IList<Option> Options { get; set; }


OPTION
---------------------------
public int Id { get; set; }
public Attribute Attribute { get; set; }
public int LanguageId { get; set; }
public string Title { get; set; }

映射如下:

<class name="Attribute" lazy="false" table="attribute" dynamic-insert="true" dynamic-update="true" select-before-update="true">
    <id name="Id" column="attribute_id" type="System.Int32">
        <generator class="native"/>
    </id>

    <bag name="Options" lazy="false" cascade="all">
        <key column="attribute_id" not-null="true" />
        <one-to-many class="Option" not-found="ignore" />
    </bag>

    <join table="attribute_i18n" inverse="true" fetch="join">
        <key column="attribute_id" not-null="true"/>
        <property name="LanguageId" column="language_id" type="System.Int32" not-null="true" />
        <property name="Title" column="title" type="System.String" length="255" not-null="true" />
    </join>
</class>

<class name="Option" lazy="false" table="options" dynamic-insert="true" dynamic-update="true" select-before-update="true">
    <id name="Id" column="option_id" type="System.Int32">
        <generator class="native"/>
    </id>

    <many-to-one name="Attribute" class="Attribute" column="attribute_id" not-null="true" />

    <join table="option_i18n" inverse="true" fetch="join">
        <key column="option_id" not-null="true"/>
        <property name="LanguageId" column="language_id" type="System.Int32" not-null="true" />
        <property name="Title" column="title" type="System.String" length="255" not-null="true" />
    </join>
</class>

请注意,这两个表都连接到其自己的“i18n”表(支持多语言条目),并参考其 language_id 列。

此外,我尝试使用 QueryOver API,并在 Options-property 中查询 LanguageId 设置为 1 的选项。

在拉了很多头发之后,我的查询又回到了我开始的地方:

Attribute attribute = null;
Option option = null;

result = Session.QueryOver(() => attribute)
                .Where(() => attribute.LanguageId == 1)
                .Left.JoinAlias(i => i.Options, () => option)
                .Where(() => option.LanguageId == 1)
                .TransformUsing(Transformers.DistinctRootEntity)
                .List();

所以,对于我的问题: 此查询不断在我的选项列表中为我提供一组双重选项(用于 language_id 1 和 2)。我只想选择 language_id = 1,但令我沮丧的是,API 不理解我(..还是反过来?)。

非常感谢有关如何使我的查询针对我的 OPTION 包集合的任何帮助! :-) 谢谢!

米卡尔

【问题讨论】:

    标签: c# mysql nhibernate queryover


    【解决方案1】:

    恐怕他的行不通。通过设计和&lt;join&gt; 的性质。如文档中所述:

    5.1.19. join

    使用&lt;join&gt; 元素,可以将一个类的属性映射到多个表,当 表之间存在 1 对 1 关系。

    (我愿意)解决这个问题的方式有点不同。我有一个对象Language,该选项有多种语言

    public virtual IList<Language> Languages {get; set;}
    

    映射例如&lt;bag&gt;

    <bag name="Languages"  batch-size="25"
      cascade="all-delete-orphan" inverse="true" >
      <key column="option_id" />
      <one-to-many class="Language" />
    
      <filter name="LanguagFilter" condition=":languageId = LanguageId" />
    </bag>
    

    诀窍在于过滤器。这是 where 映射属性(18.1. NHibernate 过滤器)的动态版本

    <filter-def name="LanguageFilter" >
      <filter-param name="languageId" type="Int32" />
    </filter-def>
    

    然后,我们可以为当前会话的所有操作打开过滤器。每个请求(如果是 Web 应用程序)只有一次,在某个 AOP 中,我们知道语言 ID:

    var filter = session.EnableFilter("LanguageFilter");
    filter.SetParameter("languageId", theCurrentLanguageIdFromUser);
    

    最后,我们知道,Languages 集合只包含一条记录,我们始终可以访问.First()。没有更多语言的多个结果

    另见:https://stackoverflow.com/a/16625867/1679310https://stackoverflow.com/a/18479266/1679310

    【讨论】:

    • 谢谢你。我会在工作后对其进行测试,但它看起来很有希望。两个快速的后续问题,如果您不介意的话:您是否会为每个实体使用一个翻译表,即 attribute_i18n 和 option_i18n ,或者对所有需要翻译的主要类使用一个翻译表会更好(也是性能副),并且有您在 where 子句中包含的额外列。你怎么看?其次;我看到您将批量大小放入映射中。这个楼盘有什么优势?谢谢!
    • batch-size 是一个很棒的设置,可以帮助我们避免 N+1 问题。 IE。如果加载了选项,则会为它们分批加载语言集合......酷而高效的功能;)表的问题是基于意见和项目的。但我所做的是尽可能减少表的数量(就像在这种情况下)并使用where 属性和discriminator 列来区分 table-row 属于哪个对象。祝 NHibernate 好运。 PS:检查这个stackoverflow.com/a/14801256/1679310
    • 似乎我没有足够的声誉来支持您的答案,但非常感谢。谢谢!:)
    • Radim:我已经更改了我的表结构和实体以支持这一点。它几乎就像一个魅力,除了我在插入新的语言条目时遇到问题。我猜 LanguageId-column 键约束在插入时失败,因为我收到此错误消息:无法添加或更新子行:外键约束失败。由于它与您的答案有关,请问您是如何解决这个问题的?谢谢:)
    • 你应该提出新问题,有很多聪明人准备提供帮助。在这种情况下(在创建期间),我们必须填充所有语言的完整列表,稍后将对其进行过滤。而且,在将它们填充到集合中时,我们必须将它们分配给它们的持有者。我正在使用Template method pattern,并在那里启动所有的东西。
    猜你喜欢
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多