Как оптимизация в запросе NHibernate и лучшая производительность - PullRequest
0 голосов
/ 09 ноября 2011

У меня есть проект, реализованный NHibernate и использующий Lazy Loading.У меня есть два класса в этом проекте: Person и PersonIdentity.Отношение между этими двумя понятиями - агрегация, означает, что у Человека есть одна Персона.

Персональное сопоставление:

<class name="Person" table="Person_Person" >

    <id name="Id" type="Int64" unsaved-value="0">
      <generator class="native" />
    </id>

    <version name="Version" />

    <property name="Name" column="Name"
              type="String(255)"  access="property" not-null="false" />

    <one-to-one name="Identity" property-ref="Person"
      class="Domain.Entities.PersonIdentity,Domain.Entities" cascade="delete" fetch="select" />

</class>

Персональное сопоставление:

    <id name="Id" type="Int64" unsaved-value="0" >
      <generator class="native" />
    </id>

    <property name="FirstName" column="FirstName" type="String(255)"  access="property" not-null="false" />

    <property name="LastName" column="LastName" type="String(255)"  access="property" not-null="false" />

    <many-to-one name="Person" column="Person_id_fk" uniqe="true" class="Domain.Entities.Person,Domain.Entities"
      outer-join="auto" fetch="select" access="property" not-null="true" />

  </class>

Моя проблема в производительности.Когда я выполняю запрос только для Person, как это:

var q = SessionInstance.Query<Person>();
IList list = q.ToList<Person>();

Я ожидаю только выполнить

SELECT * FROM Person_Person

Но, кроме того, для каждого человека в базе данных, выполнить запрос, подобный этому:

SELECT * FROM Person_Identiyt WHERE Id = 1;
SELECT * FROM Person_Identiyt WHERE Id = 2;
SELECT * FROM Person_Identiyt WHERE Id = 3;
...

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

1 Ответ

1 голос
/ 09 ноября 2011

Прокси (ленивая загрузка) никогда не используются в опциональных однозначных.

Прокси-сервер всегда означает, что что-то есть, но в случае «один-к-одному», возможно, что в другой таблице нет строк. А поскольку прокси не может удалить себя из свойства владельца (и установить для него значение null), прокси использовать нельзя.

Если ваша БД гарантирует, что всегда существует Identity (внешний ключ от Person to Identity), вы можете добавить constrained="true" к одному-одному, и NHibernate будет использовать прокси.

Обходные:

  • Всегда загружайте идентификатор (с помощью fetch="join"), чтобы избежать проблемы выбора n + 1. (Примечание: если я правильно помню, может быть ошибка, которая в этом случае все еще делает n + 1. См. NHibernate Jira.)
  • Сопоставьте ссылку как коллекцию и предоставьте свойство в своем классе Person, которое вызывает collection.SingleOrDefault(). Таким образом, вы можете использовать ленивую загрузку.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...