NHibernate,每个属性都填充了不同的select语句

时间:2010-05-12 09:30:28

标签: database nhibernate optimization

我正在检索与其他表/实体有关系的nhibernate entites列表。我注意到NHibernate没有执行JOINS并填充属性,而是检索实体,然后为每个属性调用一个select。例如,如果用户可以拥有多个角色并且我从数据库中检索用户,则Nhibernate将检索用户,然后使用另一个select语句填充角色。问题是我要检索哦,让我们说一个产品列表,这些产品具有各种多对多关系和与具有自己关系的项目的关系。最后,我留下了超过一千个DB调用来检索30个产品的列表。

我还将默认延迟加载设置为false,因为每当我将实体列表保存到会话时,我在尝试在另一个页面上检索它时会出错:LazyInitializationException:无法初始化代理

如果有人能说清楚,我会非常感激。

以下是示例sql:

SELECT   *
FROM     Product b
         LEFT JOIN Minisites mini
           ON b.MinisiteId = mini.MinisiteId
         LEFT JOIN TimeRanges tr
           ON mini.TimeRange = tr.TimeRangeId
WHERE    mini.MinisiteId = 7
          OR tr.FromDate > '3/18/2010 12:00:00 AM'
ORDER BY CASE 
           WHEN mini.MinisiteId = 7 then 1
           else 0
         end
           + CASE 
               WHEN tr.FromDate > '3/18/2010 12:00:00 AM' then 1
               else 0
             end DESC

这是我调用以检索产品的代码(我传入一个示例产品来创建查询,创建查询的实际代码太长而无法发布但查询字符串基本上就是我上面发布的内容):

Session.CreateSQLQuery(GetSqlQuery(product)).AddEntity(typeof(Product)).SetResultTransformer(new DistinctRootEntityResultTransformer()).UniqueResult().List<Product>();

从该函数我返回一个我绑定到datalist的产品列表。数据列表中包含名称,公司,州的行,当您单击它时,它会打开一个下面的框,其中包含所有产品信息,清晰度,剪切等。每个产品都与其他与其他属性有关系的属性有关系,例如,它与用户有关系,该关系与地址有关系,与国家等有关系。对于这些属性中的每一个,都会生成一个select语句。

这是我的产品hbm文件:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="IDI.Domain" namespace="IDI.Domain.Entities" default-lazy="false">
    <class name="IDI.Domain.Entities.Product,IDI.Domain" table="Product">
        <id name="ProductId" column="ProductId" type="Int32">
            <generator class="native"></generator>
        </id>    


        <set name="Specialty" generic="true" table="ProductInSpecialties" cascade="save-update" lazy="false">
            <key column="ProductId" not-null="true">
            </key>
            <many-to-many class="IDI.Domain.Entities.Specialty,IDI.Domain" column="SpecialtyId" lazy="false"> </many-to-many>
        </set>

        <!--Search By Rounds -->
        <set name="Clarity"  generic="true" table="ProductInClarity" lazy="false" >
            <key column="ProductId" not-null="true">
            </key>
            <many-to-many class="IDI.Domain.Entities.Clarity,IDI.Domain" column="ClarityId" lazy="false" > </many-to-many>
        </set>

        <set name="Color" generic="true" table="ProductInColor">
            <key column="ProductId" not-null="true">
            </key>
            <many-to-many class="IDI.Domain.Entities.Color,IDI.Domain" column="ColorId" lazy="false"> </many-to-many>
        </set>

        <set name="Carat" generic="true" table="ProductInCarat">
            <key column="ProductId" not-null="true">
            </key>
            <many-to-many class="IDI.Domain.Entities.Carat,IDI.Domain" column="CaratId" lazy="false"> </many-to-many>
        </set>

        <set name="Finish" generic="true" table="ProductInFinish" >
            <key column="ProductId" not-null="true">
            </key>
            <many-to-many class="IDI.Domain.Entities.Finish,IDI.Domain" column="FinishId" lazy="false"> </many-to-many>
        </set>
        <!--End Search By Rounds -->


        <!--Search By Fancy Cut -->
        <set name="FCShape" generic="true" table="ProductInShapes">
            <key column="ProductId" not-null="true">
            </key>
            <many-to-many class="IDI.Domain.Entities.Shape,IDI.Domain" column="ShapeId" lazy="false"> </many-to-many>
        </set>

        <set name="FCClarity" generic="true" table="ProductInFCClarity">
            <key column="ProductId" not-null="true">
            </key>
            <many-to-many class="IDI.Domain.Entities.Clarity,IDI.Domain" column="ClarityId" lazy="false"> </many-to-many>
        </set>

        <set name="FCColor" generic="true" table="ProductInFCColor">
            <key column="ProductId" not-null="true">
            </key>
            <many-to-many class="IDI.Domain.Entities.Color,IDI.Domain" column="ColorId" lazy="false"> </many-to-many>
        </set>

        <set name="FCCarat" generic="true" table="ProductInFCCarat">
            <key column="ProductId" not-null="true">
            </key>
            <many-to-many class="IDI.Domain.Entities.Carat,IDI.Domain"  column="CaratId" lazy="false" > </many-to-many>
        </set>

        <set name="FCFinish" generic="true" table="ProductInFCFinish">
            <key column="ProductId" not-null="true">
            </key>
            <many-to-many class="IDI.Domain.Entities.Finish,IDI.Domain" column="FinishId" lazy="false" > </many-to-many>
        </set>
        <!--End Search By Fancy Cut -->

        <set name="TurnOver" generic="true" table="ProductInTurnOver" lazy="false">
            <key column="ProductId" not-null="true">
            </key>
            <many-to-many class="IDI.Domain.Entities.TurnOver,IDI.Domain" column="TurnOverId" lazy="false"> </many-to-many>
        </set>

        <many-to-one name="User"  column="UserId" not-null="true" cascade="save-update" lazy="false" class="IDI.Domain.Entities.BursaUser,IDI.Domain"></many-to-one>
        <many-to-one name="Minisite"  column="MinisiteId" not-null="false" lazy="false" class="IDI.Domain.Entities.Minisite,IDI.Domain"></many-to-one>

    </class>
</hibernate-mapping>

感谢。

埃坦

1 个答案:

答案 0 :(得分:0)

修改

由于您自己指定SQL查询,因此NHibernate对查询没有任何影响来进行任何连接。

您可以做的是在map元素或实体本身的class元素上指定批量大小(不确定)。如果NHibernate认为它会有所帮助,它将做一些基本的优化和预取记录。


(老回答)

  

这是可配置的。如何,取决于配置类型(hbm,属性,流畅)。在XML中,您可以指定fetch属性:       <many-to-one fetch="join" [...] />   问题是,如果您加入太多关系,这可能会导致笛卡尔积。   也可以使用ICriteria API在每个查询的基础上设置fetchmode。   如果您要获取如此多的数据,只需要考虑一下:是否真的有必要每次获取所有数据?您是否向用户报告了所有内容?如果没有,您可以将lazy设置为false,只在需要时才获取数据。