2011-07-21 42 views
4

我在使用c#,nhibernate和鏈接時遇到了問題。在下面的例子中,我在BrandTable中做了一個SELECT,但我只需要「Name」和「Id」列。 但它總是對錶格的所有列進行選擇。 使用EntityFramework,下面的代碼只生成一個只有這兩列的選擇。只從表中選擇幾列

如何在nhibernate中做到這一點?

using (ISession session = MyConnection.GetCurrentSession()) 
     { 
      var brands = from b in session.QueryOver<BrandTable>().List() 
           orderby b.Name 
           select new Brand {Id = b.id, Name = b.Name}; 

      return brands.ToList(); 
     } 
+0

您正在訂購併在內存中應用投影,這就是爲什麼不起作用(.List()方法選擇所有記錄 – Vasea

回答

4

這是一個例子使用投影:

List results = session.CreateCriteria<BrandTable>() 
.SetProjection(Projections.ProjectionList() 
    .Add(Projections.Id(), "Id") 
    .Add(Projections.Property("Name"), "Name") 
) 
.SetResultTransformer(Transformers.AliasToBean<BrandTable>()); // edit - don't forget the result transformer! 
.List(); 

此處作爲一例使用QueryOver:

NHibernate QueryOver select entity and aggregates

[編輯] 也,目前高速緩存的ICriteria時的錯誤預測。 (如果您嘗試緩存查詢,你會得到一個例外) https://nhibernate.jira.com/browse/NH-1090 [/編輯]


Releted帖子:

NHibernate Criteria: howto exclude certain mapped properties/collections?

Only retrieve specific columns when using Critera queries?

LINQ-NHibernate - Selecting only a few fields (including a Collection) for a complex object


,使您的查詢重構安全的(沒有「魔法字符串」),可以實現像這樣:

public static class ObjectExtensions 
{ 
    public static string NameOf<T>(this T target, Expression<Func<T, object>> propertyExpression) 
    { 
     MemberExpression body = null; 
     if (propertyExpression.Body is UnaryExpression) 
     { 
      var unary = propertyExpression.Body as UnaryExpression; 
      if (unary.Operand is MemberExpression) 
       body = unary.Operand as MemberExpression; 
     } 
     else if (propertyExpression.Body is MemberExpression) 
     { 
      body = propertyExpression.Body as MemberExpression; 
     } 
     if (body == null) 
      throw new ArgumentException("'propertyExpression' should be a member expression"); 

     // Extract the right part (after "=>") 
     var vmExpression = body.Expression as ConstantExpression; 

     // Extract the name of the property 
     return body.Member.Name; 
    } 

} 

使用這樣的:

MyEntity entity = null; // don't need a 'valid' instance. 
string propName = entity.NameOf(x => x.SomePropertyName); 
+0

第二個示例不起作用,它發送所有列以查詢 –

+0

第二個示例doesn沒有工作,因爲它正在過濾內存中的集合 – Vasea

+0

我更新了帖子!thx! – danyolgiax

1

您也可以做到這一點NH中的QueryOver。下面是從http://nhforge.org/blogs/nhibernate/archive/2009/12/17/queryover-in-nh-3-0.aspx

預測採取

根類型的屬性的簡單凸起可以使用。選擇方法,其可以利用多個Lambda表達式參數被添加:

IList selection = 
    session.QueryOver<Cat>() 
     .Select(
      c => c.Name, 
      c => c.Age) 
     .List<object[]>(); 

由於這個查詢沒有更長的返回Cat,返回類型必須明確指定。

IList<int> ages = 
    session.QueryOver<Cat>() 
     .Select(c => c.Age) 
     .List<int>(); 

有如何在上面的鏈接使用突起幾個例子:如果單個屬性被投影,則返回類型可以利用來指定。

6

對於QueryOver,您不能使用查詢解析,因爲它不是Linq提供程序。在你的例子中,你實際上選擇了所有記錄,然後使用LINQ to Objects。添加NHibernate。LINQ的命名空間到您的文件,並改寫查詢作爲

from b in session.Query<BrandTable>() 
orderby b.Name 
select new Brand {Id = b.id, Name = b.Name}; 
0

您可以使用以下步驟中選擇了一個域的一些列:

  1. 創建一個小的類,你想要的字段: 例子:

private class LeadInformation 
    { 
      public string Id { get; set; } 
      public DateTime AdmissionDate { get; set; } 
    } 

  • 查詢要提取的信息在哪裏域實體
  • 
    IQueryable leads = 
           repository.Query() 
           .Where(x => x.AdmissionRepUserObj.ID.ToString() == filter.UserId 
            ).Select(lead => new LeadInformation 
            {AdmissionDate = lead.DateApplied.Value, 
            Id = lead.ID.ToString()}); 
    
    

    在以身作則的是,我們要提取信息的實體。注意目標是相同類型的目標類LeadInformation。 這會返回目標類LeadInformation的可查詢列表,只有源域類的兩列。