2011-04-23 50 views
7

我試圖產生的線沿線的SQL:使用QueryOverNHIbernate:投影所有屬性的快捷方式?

Title title = null; 

var q = session 
    .QueryOver(() => title) 
    .Select(
     Projections.Alias(Projections.Property<Title>(t => t.Id), "Id"), 
     Projections.Alias(Projections.Property<Title>(t => t.Name), "Name"), 
     .... 
     Projections.SubQuery(sq.Where(tt => tt.Id == title.Id))), "TopLevelGenre") 
) 
[code trimmed] 

有在標題15種性能,我想項目

SELECT 
    t.*, 
    SELECT (...) 
FROM Title t 
[trimmed] 

。有沒有更簡單的方法來實現這一點,以便我不必按照以上的方式單獨投影每個房產?

+0

我認爲你不想使用'HQL'? – Rippo 2011-04-25 11:12:21

+0

我更喜歡ICriteria,但我願意使用HQL。你有什麼想法? – csano 2011-04-25 20:52:52

+0

此外,如果我上面發佈的代碼是使用ICritiera完成它的唯一方法,我很感激確認。 – csano 2011-04-25 23:10:43

回答

2

我發現,從NHibernate 3.2開始,如果不手動枚舉所有的屬性,這是不可能的。

0

如果你想標題對象,你可以這樣寫:

IList<Title> list = session.QueryOver<Title>.Where(/*some condition*/).List(); 

NHibernate的將填充所有的標題屬性爲您服務。
參見here以獲得進一步的細節。

+0

感謝您的回覆。但這不是我要找的東西。正如你在我發佈的代碼中看到的那樣,我試圖除了子查詢生成的值之外,還要選擇Title表中的所有值。 – csano 2011-04-25 05:56:27

0

是否可以使用您感興趣的列在標題表上創建視圖? 或 也許你可能想嘗試在兩個類(從TitleBase類繼承的TitleBase類和Title類)中分離Title類的屬性。因此,您需要創建兩個單獨的映射文件。

假設您感興趣的所有屬性都在TitleBase類中,則在上述查詢中使用它。

1

如果你不介意ICriteria,這個工程。我已經用2.1.2進行了測試,但是我不明白爲什麼如果不能用於3.x。

var projectionList = Projections.ProjectionList(); 
var metadata = session.SessionFactory.GetClassMetadata(typeof(Title)); 
foreach (var name in metadata.PropertyNames) 
{ 
    projectionList.Add(Projections.Property(name), name); 
} 
var criteria = DetachedCriteria.For<Title>() 
    .SetProjection(projectionList) 
    ...; 
1

如果不手動枚舉所有屬性,則無法做到這一點。我通常使用CodeSmith來生成投影代碼。

0

我已經用這段代碼解決了它。我希望它能爲你服務。我只是使用Bags,如果您需要使用ISet,則只需更改比較。 PDM是我正在應用反射的屬性的實體。您可以將此方法更改爲通用。

 ProjectionList list = Projections.ProjectionList();    
     var metadata = session.SessionFactory.GetClassMetadata(typeof(PDM)); 

     foreach (var name in metadata.PropertyNames) 
     { 
      PropertyInfo property = typeof(PDM).GetProperties(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(x => x.Name.Equals(name)); 
      FieldInfo field = typeof(PDM).GetFields(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(x => x.Name.Equals(name)); 

      if (property != null) 
      { 
       if (!property.PropertyType.Name.Contains("IList")) 
       { 
        list.Add(Projections.Property(name), name); 
       } 
      } 

      if (field != null) 
      { 
       if (!field.FieldType.Name.Contains("IList")) 
       { 
        list.Add(Projections.Property(name), name); 
       } 
      } 
     }