从表中只选择几列

时间:2011-07-21 12:34:36

标签: c# .net nhibernate

我在使用c#,nhibernate和link方面遇到了问题。在下面的例子中,我在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();
        }

4 个答案:

答案 0 :(得分: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};

答案 1 :(得分: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 [/编辑]


发布的帖子:

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);

答案 2 :(得分:2)

您也可以使用NH中的QueryOver执行此操作。以下内容摘自http://nhforge.org/blogs/nhibernate/archive/2009/12/17/queryover-in-nh-3-0.aspx

预测

可以使用.Select方法添加根类型属性的简单投影,该方法可以使用多个Lambda Expression参数:

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>();

在上面的链接中还有几个如何使用投影的例子。

答案 3 :(得分:0)

您可以使用以下步骤为一个域选择一些列:

  1. 使用您想要的字段创建一个小类: 例如:
  2. 
     private class LeadInformation
      {
                public string Id { get; set; }
                public DateTime AdmissionDate { get; set; }
      }
    
    
    1. 查询域实体您要在哪里提取信息
    2. 
       IQueryable leads =
                      repository.Query()
                      .Where(x => x.AdmissionRepUserObj.ID.ToString() == filter.UserId
                          ).Select(lead => new LeadInformation 
                           {AdmissionDate = lead.DateApplied.Value,
                           Id = lead.ID.ToString()});
      
      

      在示例中,Lead是我们要提取信息的实体。观察目标与目标类LeadInformation的类型相同。 这将返回一个可查询的目标类LeadInformation列表,其中只包含源域类的两列。