【问题标题】:Selecting only a few columns from a table从表中仅选择几列
【发布时间】:2015-12-29 05:05:04
【问题描述】:

我在使用 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();
        }

【问题讨论】:

  • 您在内存中订购和应用投影,这就是为什么不起作用(.List() 方法选择所有记录。

标签: c# .net nhibernate


【解决方案1】:

您不能对 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};

【讨论】:

    【解决方案2】:

    这是一个使用投影的例子:

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

    【讨论】:

    • 第二个例子不起作用。它将所有列发送到查询。
    • 第二个例子不起作用,因为它正在过滤内存中的集合
    【解决方案3】:

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

    预测

    可以使用 .Select 方法添加根类型属性的简单投影,该方法可以采用多个 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>();
    

    上面的链接中还有几个关于如何使用投影的示例。

    【讨论】:

      【解决方案4】:

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

      1. 创建一个包含所需字段的小类: 示例:
      
       private class LeadInformation
        {
                  public string Id { get; set; }
                  public DateTime AdmissionDate { get; set; }
        }
      
      
      1. 查询域实体要提取到哪里的信息
      
       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 的可查询列表,其中只有源域类的两列。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-30
        • 1970-01-01
        • 2017-05-23
        • 2019-04-18
        相关资源
        最近更新 更多