Nhibernate - eager fetchmode,外连接 - 收集的顺序子句导致第二个不必要的查询

发布于 2025-01-01 11:20:55 字数 3202 浏览 0 评论 0原文

当我使用单个查询运行以下代码来获取产品的 3 个集合:价目表、材料和颜色。 当product.PriceList访问集合时,我有数据

ProductDTO Product = (ProductDTO)session.CreateCriteria(typeof(ProductDTO))
                .Add(Expression.IdEq(code))
                .SetFetchMode("Colors", FetchMode.Eager)
                .SetFetchMode("PriceList", FetchMode.Eager)
                .SetFetchMode("Materials", FetchMode.Eager)
                .UniqueResult();

问题是我需要按Num顺序列出集合PriceList,并且我使用以下代码:

ProductDTO Product = (ProductDTO)session.CreateCriteria(typeof(ProductDTO))
                .Add(Expression.IdEq(code))
                .SetFetchMode("Colors", FetchMode.Eager)
                .SetFetchMode("PriceList", FetchMode.Eager)
                .SetFetchMode("Materials", FetchMode.Eager)
                .UniqueResult();

或下一个代码:

ProductDTO Product = (ProductDTO)session.CreateCriteria(typeof(ProductDTO))
                .Add(Expression.IdEq(code))
                .SetFetchMode("Colors", FetchMode.Eager)
                .SetFetchMode("PriceList", FetchMode.Eager)
                .SetFetchMode("Materials", FetchMode.Eager)
                .CreateCriteria("PriceList").AddOrder(Order.Asc("Num"))
                .UniqueResult();

此限制意味着当我访问集合产品时。 PriceList 对 PriceList 强制执行新查询(不带订单子句),这是不必要的。 我偶尔会收到“延迟初始化集合角色失败,没有会话或会话已关闭”的

信息,如果有人可以指导我的话。我喜欢在单个查询中解决问题并了解会发生什么。 我发现类似的帖子,比如使用“not-found=ignore”的帖子。我正在使用 NHIBERNATE 2.1.2,

我在下面复制了部分映射:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
    <class name="DotAR.M.Logica.DTO.ProductDTO, DotAR.M" table="products">
        <id name="Code" type="string" unsaved-value="null">
            <generator class="assigned" />
       </id>
       <set name="PriceList" lazy="true" inverse="true" cascade="all">
            <key column="code" />
            <one-to-many class="DotAR.M.Logica.DTO.ProductPriceNumDTO, DotAR.M" />
       </set>

       <set name="Colors" lazy="true" inverse="true" cascade="all">
            <key column="code" />
            <one-to-many class="DotAR.M.Logica.DTO.ProductColorDTO, DotAR.M" />
       </set>
       <set name="Materials" lazy="true" inverse="true" cascade="all">
            <key column="code" />
            <one-to-many class="DotAR.M.Logica.DTO.ProductMaterialDTO, DotAR.M" />
       </set>
    </class>
</hibernate-mapping>

每个集合都有一个复合 ID。产品颜色示例

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
   <class name="DotAR.M.Logica.DTO.ProductColorDTO, DotAR.M" table="product_colors">
        <composite-id unsaved-value="any">
            <key-property name="Code" type="string" />
            <key-property name="Name" type="string" />
        </composite-id>
        <many-to-one name="Product" column="code" class="DotAR.M.Logic.DTO.ProductDTO, DotAR.M" insert="false" update="false" />
 </class>
</hibernate-mapping>

When I run the following code with a single query to get the 3 collections for the Product: pricelist, Materials and Colors.
And when product.PriceList access the collection, I have the data

ProductDTO Product = (ProductDTO)session.CreateCriteria(typeof(ProductDTO))
                .Add(Expression.IdEq(code))
                .SetFetchMode("Colors", FetchMode.Eager)
                .SetFetchMode("PriceList", FetchMode.Eager)
                .SetFetchMode("Materials", FetchMode.Eager)
                .UniqueResult();

The problem is that I need to list the collection PriceList in order by Num and I use the following code:

ProductDTO Product = (ProductDTO)session.CreateCriteria(typeof(ProductDTO))
                .Add(Expression.IdEq(code))
                .SetFetchMode("Colors", FetchMode.Eager)
                .SetFetchMode("PriceList", FetchMode.Eager)
                .SetFetchMode("Materials", FetchMode.Eager)
                .UniqueResult();

OR next code:

ProductDTO Product = (ProductDTO)session.CreateCriteria(typeof(ProductDTO))
                .Add(Expression.IdEq(code))
                .SetFetchMode("Colors", FetchMode.Eager)
                .SetFetchMode("PriceList", FetchMode.Eager)
                .SetFetchMode("Materials", FetchMode.Eager)
                .CreateCriteria("PriceList").AddOrder(Order.Asc("Num"))
                .UniqueResult();

This restriction means that when I access the collection product.PriceList FORCE a NEW QUERY for PriceList (not with order clause) that is unnecessary.
And I occasionally get "failed lazily initialize collection role no session or session was closed"

Please if anyone can guide me about it. I like to solve in a single query and understand what happens.
I found similar post like one that use "not-found=ignore". I'm using NHIBERNATE 2.1.2

I reproduce below part of the mappings:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
    <class name="DotAR.M.Logica.DTO.ProductDTO, DotAR.M" table="products">
        <id name="Code" type="string" unsaved-value="null">
            <generator class="assigned" />
       </id>
       <set name="PriceList" lazy="true" inverse="true" cascade="all">
            <key column="code" />
            <one-to-many class="DotAR.M.Logica.DTO.ProductPriceNumDTO, DotAR.M" />
       </set>

       <set name="Colors" lazy="true" inverse="true" cascade="all">
            <key column="code" />
            <one-to-many class="DotAR.M.Logica.DTO.ProductColorDTO, DotAR.M" />
       </set>
       <set name="Materials" lazy="true" inverse="true" cascade="all">
            <key column="code" />
            <one-to-many class="DotAR.M.Logica.DTO.ProductMaterialDTO, DotAR.M" />
       </set>
    </class>
</hibernate-mapping>

Every collection has a composite-id. Example ProductColor

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
   <class name="DotAR.M.Logica.DTO.ProductColorDTO, DotAR.M" table="product_colors">
        <composite-id unsaved-value="any">
            <key-property name="Code" type="string" />
            <key-property name="Name" type="string" />
        </composite-id>
        <many-to-one name="Product" column="code" class="DotAR.M.Logic.DTO.ProductDTO, DotAR.M" insert="false" update="false" />
 </class>
</hibernate-mapping>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

木森分化 2025-01-08 11:20:55

.CreateCriteria("PriceList").AddOrder(Order.Asc("Num")) -> NH 将订单应用于 ProductDTO.Num

否则它基本上就是一个无用的东西。由于 PriceList 是一个没有顺序的集合,即使数据库中的排序结果也会在客户端得到未排序的结果。您可能想要的是:

// using linq
var orderedPrices = Product.PriceList.Ordery(price => price.Num).ToList();

.CreateCriteria("PriceList").AddOrder(Order.Asc("Num")) -> NH applies the order to ProductDTO.Num.

Otherwise its basicly a noop. Since PriceList is a set which has no order even sorted results from the database will get unsorted clientside. What you probably want is:

// using linq
var orderedPrices = Product.PriceList.Ordery(price => price.Num).ToList();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文