代码之家  ›  专栏  ›  技术社区  ›  Randy Magruder

当字段不在所选输出中时,能否将Where()添加到IQueryable中

  •  -3
  • Randy Magruder  · 技术社区  · 8 年前

    假设我在一个返回IQueryable的函数中有一个2表联接,但输出是一个命名类型,它既不是两个表中的一个:

    var qry = from p in Persons 
              join h in Hobbies on p.PersonId equals h.PersonId
              select new OutputType
              {  
                  Name = p.FirstName, 
                  Hobby = h.HobbyName
              } 
    
    return qry
    

    假设现在我想接受这个返回的查询并执行以下操作:

     var newQuery = qry.Where( p=>p.Age > 18 )
    

    正如您所看到的,这是一个问题,因为IQueryable的类型是OutputType,所以我不能将where添加到一个人的年龄,除非我将age添加到OutputType。

    是否存在“闯入”IQueryable表达式树并以某种方式添加lambda以查询其中指定的源集合并向其中添加Where子句的情况?或者,我是否必须向OutputType添加一个Where字段,即使我对它的最终投影不感兴趣?

    1 回复  |  直到 8 年前
        1
  •  1
  •   Derpy    8 年前

    事后缩小视野比试图回溯更容易。下面是一个简单的例子,我喜欢将方法分层以便重用,这样它们就可以输出漂亮的sql。

    private IQueryable<Part> GetParts_Base()
    {
        //Proprietary. Replace with your own.
        var context = ContextManager.GetDbContext();
    
        var query = from c in context.Component
                    where c.Active
                    //kind of pointless to select into a new object without a join, but w/e
                    select new Part()
                    {
                        PartNumber = c.ComponentNumber,
                        Description = c.ComponentDescription,
                        Cost = c.ComponentCost,
                        Price = c.ComponentPrice
                    };
    
        return query;
    }
    
    //Exclude cost from this view
    public IEnumerable<Part_PublicView> GetParts_PublicView(decimal maxPrice)
    {
        var query = GetParts_Base();
    
        var results = from p in query
                      where p.Cost < maxPrice
                      select new Part_PublicView()
                      {
                          PartNumber = p.PartNumber,
                          Description = p.Description,
                          Price = p.Price
                      };
    
        return results;
    }
    
    public class Part_PublicView
    {
        public string PartNumber { get; set; }
        public string Description { get; set; }
        public decimal Price { get; set; }
    }
    
    private class Part : Part_PublicView
    {
        public decimal Cost { get; set; }
    }
    

    Linq to实体不会因为您提前选择了额外的列而惩罚您。正如您所看到的,sql在约束中包括Cost列,但在select中不包括Cost。

    SELECT
      1 AS [C1],
      [Extent1].[ComponentNumber] AS [ComponentNumber],
      [Extent1].[ComponentDescription] AS [ComponentDescription],
      [Extent1].[ComponentPrice] AS [ComponentPrice]
    FROM [dbo].[Component] AS [Extent1]
    WHERE [Extent1].[ComponentCost] < @p__linq__0