2009-09-17 183 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