你混合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字段是一个来自浏览器的字符串,在这种情况下,你必须在调用此方法之前将支持的字符串映射到表达式。
我还没有测试过上面的代码,但希望它能让你走上正轨。你试图做的并不是一件容易的事,所以要对自己有耐心。
祝你好运。