Убедитесь, что NHibernate лениво загрузил свойство многие-к-одному или нет - PullRequest
1 голос
/ 01 февраля 2011

У меня есть проект и человек (несколько упрощенно):

public class Project
{
    public virtual Person CreatedBy { get; set; }
}

public class Person
{
    public virtual string Username { get; set; }
}

Я получаю проект с NH Linq:

var projects = from p in session.Query<Project>()
             select p;
var project = projects.First();

и иногда с Fetch ()

var project = projects.Fetch(p => p.CreatedBy).First();

Теперь, как я могу проверить в модульном тесте, что project.CreatedBy не или с готовностью загружен (и наоборот), в зависимости от того, был ли Fetch() использовался?В моем понимании, использование Fetch () должно загружать Person, а если я не использую Fetch (), оно должно лениво загружать Person.

Я пробовал

Assert.IsTrue(NHibernateUtil.IsInitialized(project.CreatedBy));

И

NHibernateUtil.IsPropertyInitialized(project, "CreatedBy")

Но они оба возвращают true независимо от того, использую я Fetch () или нет.IsInitialized () прекрасно работает с коллекциями (один-ко-многим), например Person.Projects, но не со многими-к-одному ...

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

Сопоставление для свойства CreatedBy:

<many-to-one name="CreatedBy" class="Person" fetch="select">
  <column name="PERSON_ID" precision="10" scale="0" not-null="true" />
</many-to-one>

Я проверил сопоставление так:*

Что проходит.

Есть идеи?

Ответы [ 2 ]

5 голосов
/ 01 февраля 2011

Если NHibernateUtil.IsInitialized(project.CreatedBy) возвращает true, это потому, что оно инициализировано.

Если человек уже был загружен в сеансе, он будет инициализирован независимо от того, с нетерпением вы загружаете CreatedBy или нет, благодаря Identity Map.

0 голосов
/ 01 февраля 2011

Одним из решений, которое я вижу, является следующее:

Вместо использования авто-свойства, для CreatedBy используйте «классический свойство ', которое использует поддержку поле, как это:

private Person _createdBy;

public Person CreatedBy
{
    get { return _createdBy; }
    set { _createdBy = value; }
}

В файле сопоставления укажите, что NHibernate должен использовать поле поддержки вместо свойства:

<many-to-one name="CreatedBy" class="Person" access="field.camelcase-underscore" fetch="select">
  <column name="PERSON_ID" precision="10" scale="0" not-null="true" />
</many-to-one>

Затем самое прекрасное, что вы можете сделать, - это создать в вашем проекте модульного тестирования метод расширения, который проверяет, было ли инициализировано поле _createdBy.

К сожалению, вы не можете получить доступ к закрытым членам в методе расширения.

Поэтому, я думаю, вы могли бы создать внутренний метод в своем классе Project, который проверяет, было ли инициализировано поле _createdBy. Вам также следует использовать атрибут [InternalsVisibleTo][1], чтобы проект, содержащий ваши юнит-тесты, мог получить доступ к внутреннему методу в вашем классе Project.

public class Project
{
     private Person _createdBy;

     public Person CreatedBy
     {
        get{return _createdBy;}
        set{ _createdBy = value; }
     }

     internal IsCreatedByInitialized()
     {
          return _createdBy != null;
     }
}

В своем модульном тесте вы можете сделать это:

Assert.IsTrue (p.isCreatedByInitialized());

Обратите внимание, что если ваши юнит-тесты находятся в отдельном проекте, вам необходимо указать, что эта сборка должна иметь доступ к внутренним методам: следовательно, в вашем файле AssemblyInfo.cs проекта, в котором находится класс Project, вы должны сделать следующее:

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