2014-11-25 85 views
0

我有这样的功能 -.NET动态LINQ的OrderBy加入和嵌套对象

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或tblLife的“持续时间”字段中的“城市”字段。我称之为ReadTable(“city”,“asc”,“120”)或ReadTable(“CA.city”,“asc”,“120”)的函数。尽管编译正常并且不会运行时抛出异常,但两种方法都不起作用。

如何使它工作?

感谢,

回答

1

你混合LINQ到实体W /动态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(); 

排序依据和OrderByDescending是LINQ到实体兼容的方法,所以通过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字段是一个来自浏览器的字符串,在这种情况下,你必须在调用此方法之前将支持的字符串映射到表达式。

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

祝你好运。