2013-03-22 2 views
3

Я работаю с Fluent nHibernate в старой базе данных и имею таблицу основного пользователя и несколько таблиц расширений, содержащих дополнительную информацию о человеке. Эти таблицы расширения являются взаимно однозначными, что означает, что у человека будет только одна строка в таблице расширений, а таблица расширений должна всегда отображаться обратно одному человеку.Сопоставление таблицы расширений, которая может не иметь строки

Таблица: Человек
Колонны: PersonId, FirstName, LastName и т.д.

Стол: PersonLogin
Колонны: PersonID (FK, уникальный), имя пользователя, пароль и т.д.

У меня есть мои сопоставления, определенные этим (с несоответствующими свойствами опущены):

public PersonMap() 
{ 
    Table("Person"); 
    Id(x => x.Id, "PersonID").Not.Nullable(); 
    References(x => x.Login, "PersonID").LazyLoad(); 
} 

public LoginMap() 
{ 
    Table("PersonLogin"); 
    Id(x => x.Id, "PersonID").GeneratedBy.Foreign("Person"); 
    References(x => x.Person, "PersonID").LazyLoad(); 
} 

Это работает, когда у меня есть данные по обеим таблицам, но недавно я узнал, что некоторые из таблиц расширения не имеют данных для всех строк Person. Это заставило меня получить ошибки во время запроса. Таким образом, я добавил .NotFound.Ignore() моим PersonMap делает его выглядеть следующим образом:

References(x => x.Login, "PersonID").LazyLoad().NotFound.Ignore(); 

Это заставило меня, чтобы получить ненужные выбирает из таблицы Вход из-за https://nhibernate.jira.com/browse/NH-1001, когда мой бизнес слой не нужно проецировать любой из таблицы расширения значения. Это приводит к тому, что производительность может быть ужасной в некоторых моих поисковых запросах.

Я просмотрел много сообщений, но не нашел солидного ответа о том, как решить этот сценарий. Ниже приведены параметры, которые я пробовал:


Вариант один:

Создание строк на столе расширения, чтобы гарантировать, что нет ни одного человека, без ряда на столе расширения, а затем удалите .NotFound.Ignore().

Проблема с этой опцией заключается в том, что она представляет собой устаревшую базу данных, и я не уверен, где мне нужно будет обновлять, чтобы обеспечить добавление PersonLogin при вставке Person.


Вариант второй:

Удалите ссылку PersonLogin из моего PersonMap и пользовательских загрузить его внутри моего класса Person. Как это:

public class Person 
{ 
    /// <summary> Gets or sets the PersonID </summary> 
    public virtual int Id { get; set; } 

    private bool loadedLogin; 
    private PersonLogin login; 
    public virtual PersonLogin Login 
    { 
     get 
     { 
      if (!loadedLogin) 
      { 
       login = SessionManager.Session().Get<PersonLogin>(Id); 
       loadedLogin = true; 
      } 

      return login; 
     } 
     set 
     { 
      login = value; 
      loadedLogin = true; 
     } 
    } 
} 

Проблема у меня с ним в том, что я не могу с готовностью принести данные при выполнении запроса, чтобы потянуть назад большое количество объектов Person и их логинов.


Вариант третий:

Я только начал играть, чтобы увидеть, если я мог бы написать обычай IEntityNotFoundDelegate не выбрасывать исключение для этих объектов.

private class CustomEntityNotFoundDelegate : IEntityNotFoundDelegate 
{ 
    public void HandleEntityNotFound(string entityName, object id) 
    { 
     if (entityName == "my.namespace.PersonLogin") 
     { 
      return; 
     } 
     else 
     { 
      throw new ObjectNotFoundException(id, entityName); 
     } 
    } 
} 

И я добавил это в конфиг

cfg.EntityNotFoundDelegate = new CustomEntityNotFoundDelegate(); 

Он ловит мой сценарий и возвращается назад, теперь вместо того, чтобы выбросить эту ошибку, но теперь, когда я пытаюсь спроецировать эти PersonLogin свойства на мой бизнес-объектов, он пытается использовать объект Proxy и выдает эту ошибку, которую я пытаюсь выяснить, могу ли я обрабатывать чисто (возможно, в IPostLoadEventListener).

System.Reflection.TargetException occurred 
Message = Non-static method requires a target 
+0

Похоже, вы нашли решение сейчас. Мы стараемся хранить все в форме Q & A: 1 вопрос и 0 или много ответов. Я переработал некоторые из ваших «ответов», которые выглядят так, будто они действительно больше информации на вопрос, а не ответ, но последнее, по крайней мере, похоже, что часть его действительно является частью ответа. Было бы здорово, если бы вы могли отредактировать это, чтобы сохранить стиль Q & A немного лучше, чем мне удалось. – Flexo

+0

Спасибо @Flexo. Я изначально написал все вместе, но решил опубликовать варианты в виде отдельных ответов, так как я думал, что это обеспечило лучшее обсуждение и позволило людям сбрасывать плохие варианты. Во всяком случае, я очистил сообщение и ответ и принял его. Спасибо! –

ответ

1

Я думаю, что сейчас у меня это работает, сохранив .NotFound.Ignore().

я первоначально заявил:

Это заставило меня, чтобы получить ненужные выбирает из таблицы Вход в связи с https://nhibernate.jira.com/browse/NH-1001, когда мой бизнес слой не нужно проецировать любое из значений таблицы расширения. Это приводит к тому, что производительность может быть ужасной в некоторых моих поисковых запросах.

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

Я думал, что мои запросы не проецируют эти таблицы расширений, но выяснили, что у меня есть метод ToKeyValuePair, который я использовал в проецировании, чтобы объединить идентификатор и поле имени вместе с некоторыми связанными свойствами. Этот метод заставлял объекты полностью загружаться, так как LINQ не смог определить, что необходимые поля присутствовали без присоединения к таблице расширений.