代码之家  ›  专栏  ›  技术社区  ›  Thomas Stock

订购linq查询

  •  3
  • Thomas Stock  · 技术社区  · 17 年前

    对于我的通用网格,我当前执行此操作以激活排序:

    Elements.OrderBy(column.SortExpression).AsQueryable();
    

    Func<T, object> 列是一个泛型类 Column<T>

    我在控制器中设置SortExpression,如下所示:

    new Column<OrderViewData>{Key = "ShippingDate", SortExpression = e => e.ShippingDate}
    

    “OrderBy”导致执行sql语句,这是我不希望看到的。

    所以我试着用这个来代替它:

    Elements = from element in Elements
               orderby column.SortExpression
               select element;
    

    这不会触发sql执行。

    我应该仍然能够以某种通用的强类型方式设置SortExpression。

    @耳塞:

    这项工作:

    Expression<Func<Employee, DateTime?>> sortexpression = e => e.BirthDate;
    var db = new NorthwindDataContext();
    var query = from e in db.Employees
                select e;
    query = query.OrderBy(sortexpression);
    int count = query.Count();
    

    并生成:

    SELECT COUNT(*) AS [value]
    FROM [dbo].[Employees] AS [t0]
    

    Expression<Func<Employee, object>> sortexpression = e => e.BirthDate;
    

    我得到一个InvalidOperationException:无法按类型“System.Object”排序

    Expression<Func<Employee, some_type>> SortExpression = e => e.BirthDate ,其中我利用泛型列类来定义“T”。

    您认为有可能创建某种扩展,以某种方式获得 e.BirthDate 到 Expression<Func<T,some_type>> ? 然后我可以在内部代码中执行以下操作: Elements.OrderBy(column.SortExpression.FixCast())

    我现在不太在乎我的内部代码是否丑陋或复杂。我需要获得正确的SQL查询&注意使用网格的开发人员的可用性。

    非常感谢你帮了我的忙!

    var gridBuilder = new RainbowGridBuilder<Employee>("Examples_Employees")
    {
        Elements = GetEmployees(), //The elements (records) we will show in our grid. 
    
        //Define the columns for our grid.
        Columns = new List<Column<Employee>>{
                new Column<Employee> {
                    Key = "EmployeeId",                             //Key is used for sorting, selecting columns, ...
                    Header = "Employee Id",                         //The header of the column. Also used as caption in the column selection checkboxlist.
                    ValueExpression = e => e.EmployeeID.ToString(), //The Linq expression which will be executed on each element to fill the cell
                    SortExpression = e => e.EmployeeID,             //The Linq expression by which to sort the elements in the grid. 
                    Display = false},                               //Is this column visible by default?
                new Column<Employee> {Key = "Name", ValueExpression = e => e.FirstName + " " + e.LastName, SortExpression = e => e.LastName},
            },
    
        // Some other properties here that are irrelevant.
    
    
    }
    
    4 回复  |  直到 17 年前
        1
  •  3
  •   Daniel Earwicker    17 年前

    SortExpression应为以下类型 Expression<Func<T, object>> .

    通过让它成为一个 Func<T, object> ,使编译器直接将其缩减为IL,准备执行。LINQtoSQL(或实体,或NHibernate,或其他)需要以表达式树的形式捕获代码,以便将其转换为SQL或其他查询语言,以便在其他地方执行。通过将lambda指定给 Expression<Func<...>> 触发对表达式树的编译。

    你把这个放进去行吗?

    Elements = Elements.OrderBy(e => e.ShippingDate);
    

    这个怎么样?

    Expression<Func<OrderViewData, object>> sortExpression = e => e.ShippingDate;
    Elements = Elements.OrderBy(sortExpression);
    

    根据您更新的问题,听起来您需要捕获一个带有静态类型化返回值的表达式,而不是 object .

    很难知道什么是您的理想安排,但在您最初的设置代码中,您有:

    new Column<OrderViewData>{Key = "ShippingDate", SortExpression = e => e.ShippingDate}
    

    Column 取了两个类型参数, TElem (列中存储的值的类型)和 TSort (要排序的值的类型)。

    new Column<Employee, DateTime?> { SortExpression = e => e.BirthDate }
    

    SortExpression 那就是:

    Expression<Func<TElem, TSort>> SortExpression { get; set; }
    
        2
  •  1
  •   Thomas Stock    17 年前

    我想出了一个解决方案,实现了我的目标。

    用法:在列上设置强类型sortexpression:

    Columns = new List<Column<Employee>>{
                new Column<Employee> {
                    Key = "EmployeeId",   
                    SortExpression = new SortExpression<Employee>(e => e.EmployeeID)
                    // ... other irrelevant column properties ...  
                },
                new Column<Employee> {
                    Key = "EmployeeBirthDate",      
                    SortExpression = new SortExpression<Employee>(e => e.BirthDate)
                }
              };
    

    RainbowGridBuilder类中“buildGrid()”方法中的这几行应用排序:

    if (columnToSort != null) //sort the elements according to the set column key and the sortexpression
    {
        var column = Columns.Where(c => c.Key == columnToSort).SingleOrDefault();
        if (column != null)
        {
            Elements = column.SortExpression.ApplySortExpression(Elements, descending);
        }
    }
    

    工作原理:

    通过在我创建的SortExpression类中使用重载构造函数,我可以设置私有 Expression<Func<T, some_specific_Type>> .

    public class SortExpression<T>
    {
        private Expression<Func<T, DateTime?>> DateTimeExpression { get; set; }
        private Expression<Func<T, int?>> intExpression { get; set; }
        private Expression<Func<T, string>> stringExpression { get; set; }
    
        public SortExpression(Expression<Func<T, DateTime?>> expression)
        {
            DateTimeExpression = expression;
        }
    
        public SortExpression(Expression<Func<T, int?>> expression)
        {
            intExpression = expression;
        }
    
        public SortExpression(Expression<Func<T, string>> expression)
        {
            stringExpression = expression;
        }
    
        public IQueryable<T> ApplySortExpression(IQueryable<T> elements, bool? descending)
        {
            if (DateTimeExpression != null)
            {
                if (descending.HasValue && descending.Value)
                    return elements.OrderByDescending(DateTimeExpression);
                else
                    return elements.OrderBy(DateTimeExpression);
            }
            else if (intExpression != null)
            {
                if (descending.HasValue && descending.Value)
                    return elements.OrderByDescending(intExpression);
                else
                    return elements.OrderBy(intExpression);
            }
            else if (stringExpression != null)
            {
                if (descending.HasValue && descending.Value)
                    return elements.OrderByDescending(stringExpression);
                else
                    return elements.OrderBy(stringExpression);
            }
            else
                throw new Exception("Unsuported sortkey type");
        }
    }
    

    这个解决方案可能不是非常干净,但它是我追求的可用性。对消费代码的唯一更改是添加“ new SortExpression<Employee> ".

        3
  •  0
  •   jrista    17 年前

    我认为问题的根源在于你做了OrderBy 之前 正在转换为可查询的。如果您订购的是IEnumerable<T>,那你需要先点些东西。与IQueryable不同<T>,IEnumerable<T>不构建表达式树…它将一个可枚举项包裹在另一个可枚举项周围。要获得延迟执行的好处,您需要确保从一开始就使用IQueryable。在完成所有过滤、排序等操作后转换为一个不会带来任何好处。

        4
  •  0
  •   Abdul Rahman A Samad Islam Abdalla    12 年前

            var SampleData = new SampleDataContext();
    
            var text = from i in SampleData.Events
                       select i;
            var text2 = text.OrderByDescending(i => i.id);
            return View(text2);