Добавление NHibernate в дочерний набор приводит к запросу с большим или слишком большим количеством возвращаемых строк. - PullRequest
1 голос
/ 06 декабря 2010

У меня проблема в том, что когда я добавляю объект в дочернюю коллекцию, которая является набором, NHibernate делает выбор всех дочерних объектов в коллекции.Это приводит к предупреждению «Большое количество возвращенных строк» ​​в NHProf и, наконец, если в коллекции достаточно объектов для исключения System.OutOfMemoryException.

Редактировать: Версия NHibernate была 3.0.0 Beta 2

Редактировать 2: Решил это, превратив коллекцию OrderPositions в сумку.Тем не менее, было бы интересно узнать, как избежать такого дорогостоящего запроса, если набор необходим.

Редактировать 3: Подумайте об этом еще немного.Поскольку равенства и getHash реализованы в классе c #, у NH, вероятно, нет способа определить, может ли он добавить элемент в набор, отличный от заполнения всего набора и попытки фактического добавления элемента в него.Все еще будучи в состоянии сказать NH, как он может определить равенство в файле hbm, скажем, было бы замечательно ограничение естественного идентификатора.Возможно ли это?

Вот запрос, который NHibernate создает, когда я вызываю someOrder.AddOrderPosition (someOrderPosition);

SELECT orderposit0_.OrderId              as OrderId1_,
       orderposit0_.OrderPositionId      as OrderPos1_1_,
       orderposit0_.OrderPositionId      as OrderPos1_4_0_,
       orderposit0_.OrderedAmount        as OrderedA3_4_0_,
       orderposit0_.OrderId              as OrderId4_0_,
       orderposit0_.ArticleId            as ArticleId4_0_
FROM   OrderPositions orderposit0_
WHERE  orderposit0_.OrderId = 3889 /* @p0 */

Вот пример кода:

public class Order : Entity<int>
{
    private ISet<OrderPosition> orderPositions = new HashedSet<OrderPosition>();

    public virtual DateTime OrderDate { get; set; }

    public virtual ISet<OrderPosition> OrderPositions
    {
        get
        {
            return this.orderPositions;
        }

        protected set
        {
            this.orderPositions = value;
        }
    }

    public virtual void AddOrderPosition(OrderPosition orderPosition)
    {
        if (orderPosition.Order != null)
        {
            orderPosition.Order.OrderPositions.Remove(orderPosition);
        }

        orderPosition.Order = this;
        this.OrderPositions.Add(orderPosition);
    }
}


public class OrderPosition : Entity<int>
{
    public virtual int OrderedAmount { get; set; }

    public virtual Order Order { get; set; }

    public virtual Article Article { get; set; }
}


<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="DataTransfer" namespace="DataTransfer">
  <class name="Order" table="Orders">
    <id name="Id" column="OrderId">
      <generator class="native" />
    </id>
    <set name="OrderPositions" inverse="true" cascade="all-delete-orphan">
      <key column="OrderId" />
      <one-to-many class="OrderPosition" />
    </set>
  </class>
</hibernate-mapping>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"  assembly="DataTransfer" namespace="DataTransfer">
  <class name="OrderPosition" table="OrderPositions">
    <id name="Id" column="OrderPositionId">
      <generator class="native" />
    </id>
    <property name="OrderedAmount" />
    <many-to-one name="Order" column="OrderId" cascade="all" />
    <many-to-one name="Article" column="ArticleId" cascade="all" />
  </class>
</hibernate-mapping>

Ответы [ 2 ]

1 голос
/ 07 декабря 2010

Проблема в семантике набора и сумки. Сумка - это неупорядоченная коллекция предметов, которая может содержать дубликаты. Набор представляет собой неупорядоченную коллекцию элементов без дубликатов. Следовательно, NHibernate должен выполнить выборку на основе дочерней коллекции, чтобы убедиться, что дубликатов не существует перед сохранением.

0 голосов
/ 06 декабря 2010

Попытка добавить несохраненное значение к вашему элементу <id> в вашем отображении OrderPositions. Например:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"  assembly="DataTransfer" namespace="DataTransfer">
  <class name="OrderPosition" table="OrderPositions">
    <id name="Id" column="OrderPositionId" unsaved-value="0">
      <generator class="native" />
    </id>
    <property name="OrderedAmount"
    <many-to-one name="Order" column="OrderId" cascade="all" />
    <many-to-one name="Article" column="ArticleId" cascade="all" />
  </class>
</hibernate-mapping>

У меня не было возможности проверить это, но я предполагаю, что, поскольку нет никакого способа узнать, была ли ранее сохранена сущность, она проверяет, существует ли она уже. unsaved-value позволяет NHibernate знать, что объект не был сохранен ранее.

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