2009-09-17 110 views
5

使用NHibernate我想過濾一個類中的集合只包含可能對象的一個​​子集。下面我將包含一個示例表格數據來幫助解釋。我無法找到使用NHibernate的方法。NHibernate過濾器集合

表:數據對象

DataObjectId(PK)/名稱/ 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> 

回答

11

如果要過濾按需採集,使用過濾器是一個有效的選擇。 您需要在Version類和bag元素上聲明過濾器,並應用NHibernateSession.EnableFilter方法中的過濾器

如果您始終想要在包中獲取單個版本,然後實現'where'在袋的映射:

<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可以是o verkill。 應用在類的公式屬性和DataObjectVersion對象可能更合適

在類數據對象與

public virtual DataObjectVersion Version { get; set; } 

和在映射替換IList中與線的東西取代「袋」

<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允許

我用計算性能與原生類型(日期時間,字符串等),並獲取一個實體可以(或可能不會)需要更多的東西或不同

最後但並非最不重要的,你可以在收集後應用一個過濾器,你已經通過創建獲取的主要對象數據對象在收集

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

的濾波器,其中do.Versions收集沒有被初始化,只有單獨的fVersion集合中取出的結果,這是一個第二SELECT已經作出的往返的分貝爲後DataObject獲取。

+0

謝謝你的幫助。 – 2016-08-31 21:49:47

0

想必你VERSIONNUMBER增量爲用戶更改數據和你想獲得最新的一個。如果您將VersionNumber視爲「年齡」字段(即0代表最新版本/最新版本,1代表下一個最早版本等),那麼您的問題就變成了如何獲得年齡爲0的所有實體。使用過濾器完成:http://nhibernate.info/doc/nh/en/index.html#objectstate-filters