2012-12-07 50 views
0

我試圖限制結果集映射的集合。限制子實體不限制父實體 - NHibernate的

下面是一個簡單的模型:

public class Table1 { 
    public virtual long Id { get; set; } 
    public virtual IList<Table2> Table2s { get; set; } 
} 


public class Table2 { 
    public virtual long Id { get; set; } 
    public virtual long Table1Id { get; set; } 
    public virtual Table1 Table1 { get; set; } 
    public virtual string Field { get; set; } 
} 

public class Table1Map : ClassMap<Table1> { 
    public Table1Map() { 
     Table("Table1"); 
     Id(x => x.Id).Column("Id").Not.Nullable().CustomType("Int64").GeneratedBy.Native(); 
     HasMany<Table2>(x => x.Table2s).Inverse().Not.LazyLoad().KeyColumns.Add("Table1Id").Fetch.Join(); 
    } 
} 

public class Table2Map : ClassMap<Table2> { 
    public Table2Map() { 
     Table("Table2"); 
     Id(x => x.Id).Column("Id").Not.Nullable().CustomType("Int64").GeneratedBy.Native(); 
     Map(x => x.Table1Id).Column("Table1Id").Not.Nullable().CustomType("Int64"); 
     Map(x => x.Field).Column("Field").Not.Nullable().CustomType("AnsiString").Length(25); 
     References<Table1>(x => x.Table1, "Table1Id").Cascade.None(); 
    } 
} 

我想選擇所有Table1秒。我也想選擇所有Table2 s表示符合一定條件(Table2.Field = 'value'),但我不希望限制我Table1 S,所以選擇空Table2■如果他們不符合標準。如果我想這樣做在SQL我會做到以下幾點:

SELECT * 
FROM 
Table1 
LEFT OUTER JOIN Table2 ON Table1.Id = Table2.Table1Id 
WHERE 
Table2.Field = 'value' or Table2.Field IS NULL 

我應該如何構建我的NHibernate的查詢,達到預期的效果?我想要列出一個Table1 s,並且在每個Table1中,我想要一個空列表Table2 s(因爲沒有Table2 s符合標準),或者列表符合該標識的Table2 s。

我試圖像下面,但這顯然是不行的:

List<Table1> result = new List<Table1>(); 
IQueryable<Table1> query = session.Query<Table1>(); 
if (value != null) { 
    query = query.Where(x => x.Table2s.Field == value); 
} 
query = query.OrderBy(x => x.Id); 
result = query.ToList(); 

回答

0

我覺得這是不可能的,你這樣做的方法。 Hibernate將加載具有其所有屬性的完整實體(如果未啓用延遲加載)。 如果你保存這樣一個table1類型的加載實體而不是所有的table2,hibernate應該做什麼?

您應該創建某種包含的表1的相關部分,並且符合標準表2孩子的列表的ViewObject(DVO)的。選擇可能由projection完成。

0

有相當不錯的文檔 - 16.4。協會

http://nhibernate.info/doc/nh/en/index.html#queryqueryover-associations

QueryOver語法看起來像這樣

IQueryOver<Table1, Table2> myQuery = 
    session.QueryOver<Table1>() 
    .Left.JoinQueryOver<Table2>(t => t.Table2s) 
    .Where(
     Restrictions.Or(
     Restrictions.On<Table2>((t2) => t2.ID).IsNull, 
     Restrictions.On<Table2>((t2) => t2.Field).IsLike("value") 
     ) 
     ); 
var list = myQuery.List<Table1>(); 

那麼list將返回符合條件的所有組合的集合。 (或由不同的或其他porjections後來爲了可以添加...)

+0

這是一個很好的答案,但一定程度限制。如果'Table1'不僅有'Table2'的集合,而且'Table3'也是你想要過濾的。所提供的方法僅適用於兩個實體。有更通用的方法嗎?還有另一種方法嗎?謝謝! – Michael

+0

是的! ;)NHibernate Criteria API非常強大。你可以使用投影(選擇一些屬性,選擇distinct ... sum,avg),你可以加入任何......你可以在WHERE子句中過濾......任何東西。請看看文檔(http://nhforge.org/doc/nh/en/index.html#querycriteria)或Ayende的博客 –

+0

你有一個工作的例子嗎?我沒有找到對我的例子特別有用的文檔。我試圖實現你的建議,忽略了現在的「表3」,並沒有得到任何結果。如果您有一個使用強大的Criteria API和多個映射集合的工作示例,那將非常有幫助! – Michael