【问题标题】:.NET Dynamic LINQ OrderBy Joined and Nested Objects.NET 动态 LINQ OrderBy 连接和嵌套对象
【发布时间】:2014-11-25 00:41:07
【问题描述】:

我有这样的功能-

public void ReadTable(string sortField, string sortOrder, string RegID)
{
    sortOrder = sortOrder == "desc" ? "descending" : "";

    var db = new MyEntities();


    var results = (from CA in db.tblCalifornia
                       join BN in db.tblBeach on CA.BeachID equals BN.BeachID into ps
                       from BN in ps.DefaultIfEmpty()
                   where CA.RegID == regID && CA.tblLife.duration != null
                   orderby sortField + " " + sortOrder
                   select new { CA, BN }).ToList();
 }

我想使用 tblCalifornia 中名为“city”的字段或 tblLife 中的“duration”字段进行动态排序。

我将该函数称为 ReadTable("city", "asc", "120") 或 ReadTable("CA.city", "asc", "120")。两种方法都行不通,尽管编译正常并且没有抛出运行时异常。

如何让它发挥作用?

谢谢,

【问题讨论】:

    标签: .net linq entity-framework c#-4.0 dynamic


    【解决方案1】:

    您正在将 Linq-To-Entities 与动态 sql 混合使用 - 这是行不通的。运行时正在从您的 linq 查询构建 sql 查询,它不了解如何将 orderby 子句中的原始字符串转换为动态 SQL。

    这会让你接近:

    var q = (from CA in db.tblCalifornia
               join BN in db.tblBeach on CA.BeachID equals BN.BeachhID into ps
               from BN in ps.DefaultIfEmpty()
               where CA.RegID == regID && CA.tblLife.duration != null
               select new { CA, BN }
            );
    if (order == "desc") {
         q = q.OrderByDescending(m => m.CA.city);
    }
    else {
         q = q.OrderBy(m => m.CA.city); 
    }
    var results = q.ToList();
    

    OrderBy 和 OrderByDescending 是 Linq-To-Entities 兼容的方法,因此 SQL 生成的顺序可以正常工作。注意;但是,我明确地将他们使用的表达式设置为 CA.city。 不幸的是,我认为单独使用 EF 无法动态设置您想要的排序。

    如果您真的想这样做,请查看 LinqKit http://www.albahari.com/nutshell/linqkit.aspx

    它的“AsExpandable()”方法将允许您将表达式传递到您的方法中,然后您可以编译并插入到您的 linq 查询中。

    所以你的新方法最终会被这样调用:

    ReadTable("asc", m => m.CA.City, "120");
    

    您必须为 CA 和 BN 创建一个显式包含类,然后使用如下表达式

    public class Container {
        public tblCalifornia CA { get; set; }
        public tblBeach BN { get; set; }
    }
    public void ReadTable(string sortOrder, Expression<Func<Container,string>> fnSortExpr, string regID) {
    
        var sort = fnSortExpr.Compile();
        var q = (from CA in db.tblCalifornia.AsExpandable() 
               join BN in db.tblBeach on CA.BeachID equals BN.BeachhID into ps
               from BN in ps.DefaultIfEmpty()
               where CA.RegID == regID && CA.tblLife.duration != null
               select new Container { BN = BN, CA = CA }
            );
        if (order == "desc") {
           q = q.OrderByDescending(sort);
        }
        else {
           q = q.OrderBy(sort); 
        }
        var results = q.ToList();
        ...
    }
    

    AsExpandable() 围绕 IQueryable 创建一个包装器,它允许运行时将您的表达式转换为 LINQ-To-Entities 可以理解的东西。您首先必须在表达式上调用 .Compile(),然后在新的可扩展 IQueryable 中使用它。我假设您的 sortBy 字段是来自浏览器的字符串,在这种情况下,您必须在调用此方法之前将支持的字符串映射到表达式。

    我没有测试上面的代码,但希望它能让你走上正轨。你想要做的绝不是一件容易的事,所以对自己要有耐心。

    祝你好运。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-28
      • 2014-06-02
      • 2019-09-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多