Коллекция фильтров NHibernate - PullRequest
       16

Коллекция фильтров NHibernate

5 голосов
/ 17 сентября 2009

Используя NHibernate, я хочу отфильтровать коллекцию в классе, чтобы он содержал ТОЛЬКО подмножество возможных объектов. Ниже я приведу пример таблицы данных, чтобы помочь объяснить. Я не могу найти способ сделать это с помощью NHibernate.

Таблица: DataObject

DataObjectId (PK) / Name / CurrentVersion

11          "data.txt"      2
12          "info.txt"      3

Таблица: DataObjectVersion

Id / Комментарий / VersionNumber / DataObjectId (FK)

31   "Genesis"         1          11     <= Ignore this object
32   "Changed data"    2          11     <= Get this object
34   "Genesis"         1          12     <= Ignore this object   
35   "Changed info"    2          12     <= Ignore this object
36   "Added info"      3          12     <= Get this object

Я хочу присоединиться к внешнему ключу DataObject.CurrentVersion = DataObjectVersion.VersionNumber для каждого объекта DataObject в одной команде.

Вот классы и файлы сопоставления:

public class DataObject
{
  public virtual int DataObjectId { get; set; }
  public virtual string Name { get; set; }
  public virtual int CurrentVersionNumber { get; set; }
  public virtual IList<DataObjectVersion> Versions { get; set; }
}

<class name="DataObject" table="DataObject" lazy="false">
    <id name="DataObjectId" column="DataObjectId" type="int">
      <generator class="assigned" />
    </id>
    <property name="Name" column="Name" type="String(512)" />
    <property name="CurrentVersionNumber" column="CurrentVersionNumber" type="int" />
    <bag name="Versions" cascade="all-delete-orphan" inverse="true" lazy="false" >
        <key column="DataObjectId" />
        <one-to-many class="DataObjectVersion" />
    </bag>
</class>

public class DataObjectVersion
{
    public virtual int DataObjectVersionId { get; set; }
    public virtual string Comment { get; set; }
    public virtual int VersionNumber { get; set; }
    public virtual int DataObjectId { get; set; }
}

<class name="DataObjectVersion" table="DataObjectVersion" lazy="false">
    <id name="Id" column="DataObjectVersionId" type="int">
      <generator class="assigned" />
    </id>
    <property name="Comment" column="Comment" type="String(512)" />
    <property name="VersionNumber" column="VersionNumber" type="int" />
    <property name="DataObjectId" column="DataObjectId" type="int" />
</class>  

Ответы [ 2 ]

11 голосов
/ 18 сентября 2009

, если вы хотите фильтровать коллекцию по требованию, использование фильтра является правильным выбором. Вам необходимо объявить фильтр как для класса Version, так и для элемента bag, и применить фильтр из метода NHibernateSession.EnableFilter

, если вы всегда хотите получить одну версию в сумке, тогда укажите «где» в отображении сумки:

<bag name="Versions" cascade="all-delete-orphan" inverse="true" lazy="false" where="CurrentVersionNumber = Versions.VersionNumber" >
    <key column="DataObjectId" />
    <one-to-many class="DataObjectVersion" />
</bag>

обратите внимание, что в «где» вы пишете правильный SQL, а не HQL, и, следовательно, правильный SQL, который я пишу выше, вероятно, должен быть изменен, чтобы отражать вашу схему

Кроме того, если для извлечения одного предмета необходимо установить сумку, и соответствующий IList может быть излишним. Применение свойства формулы и объекта DataObjectVersion в классе может быть более подходящим

в классе DataObject замените IList на

public virtual DataObjectVersion Version { get; set; }

и в отображении замените 'сумку' на что-то вроде

<property name="Version" type="DataObjectVersion" update="false" insert="false" formula="(select v.DataObjectVersionId, v.Comments, v.VersionNumber, v.DataObjectId from DataObjectVersion v where v.VersionNumber  = CurrentVersionNumber)" />

опять разрешен только правильный SQL

Я использовал вычисленные свойства с собственными типами данных (дата, время, строка и т. Д.), И для извлечения сущности может (или не может) потребоваться что-то большее или другое

И последнее, но не менее важное: вы можете применить фильтр к коллекции после того, как вы выбрали первичный объект DataObject, создав фильтр для коллекции

IList<DataObjectVersion>  fVersion = 
    NHibernateSession.CreateFilter(do.Versions, "where VersionNumber = :ver")
        .SetParameter("ver", do.CurrentVersionNumber)
        .List<DataObjectVersion>();

там, где коллекция do.Versions не инициализирована, только результаты, извлеченные в отдельном собрании fVersion, и это второй SELECT после того, как уже выполнен возврат в базу данных для выборки DataObject.

0 голосов
/ 17 сентября 2009

Предположительно ваш VersionNumber увеличивается по мере того, как пользователь изменяет данные, а вы пытаетесь получить самую последнюю. Если вместо этого вы рассматриваете VersionNumber как поле «Возраст» (т. Е. Где 0 - самая последняя / самая младшая версия, 1 - следующая самая старая и т. Д.), То возникают проблемы с получением всех объектов с возрастом 0. Это быть сделано с использованием фильтра: http://nhibernate.info/doc/nh/en/index.html#objectstate-filters

...