NHibernate, каждое свойство заполняется различным оператором выбора - PullRequest
0 голосов
/ 12 мая 2010

Я получаю список объектов nhibernate, которые связаны с другими таблицами / объектами. Я заметил, что вместо NHibernate, выполняющего JOINS и заполняющего свойства, он извлекает сущность, а затем вызывает select для каждого свойства. Например, если у пользователя может быть много ролей, а я извлекаю пользователя из БД, Nhibernate извлекает пользователя и затем заполняет роли другим оператором выбора. Проблема в том, что я хочу получить, скажем, список продуктов, которые имеют различные отношения «многие ко многим» и отношения к элементам, которые имеют свои собственные отношения. В итоге у меня осталось более тысячи вызовов БД для получения списка из 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>();

Из этой функции я возвращаю список продуктов, которые привязываю к списку данных. У списка данных есть строки с именем, компанией, государством, и когда вы щелкаете по нему, он открывается в поле внизу со всей информацией о продукте, ясностью, вырезкой и т. Д. Каждый продукт имеет отношение к другим свойствам, которые имеют отношение к другим, например, он будет иметь отношение к пользователю, который имеет отношение к адресу, который имеет отношение к стране и т. д. Для каждого из этих свойств делается оператор выбора.

Вот мой файл 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 голосов
/ 12 мая 2010

EDIT

Поскольку вы сами задаете SQL-запрос, NHibernate не влияет на запрос для каких-либо объединений.

Что вы можете сделать, это указать размер пакета для элементов map или class элементов самой сущности (не уверен). NHibernate выполнит некоторые элементарные записи оптимизации и предварительной выборки, если посчитает, что это поможет.


(старый ответ)

Это настраивается. Как, зависит от типа конфигурации (хбм, атрибуты, бегло). В XML вы можете указать атрибут fetch: <many-to-one fetch="join" [...] /> Проблема в том, что это может привести к декартову произведению, если вы вступаете в слишком много отношений. Также можно использовать API-интерфейс ICriteria для установки режима выборки для каждого запроса. Если вы получаете столько данных, просто подумайте: действительно ли необходимо получать все данные каждый раз? Вы все докладываете пользователю? Если нет, вы можете установить для lazy значение false и извлекать данные только в случае необходимости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...