你混合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字段是一個來自瀏覽器的字符串,在這種情況下,你必須在調用此方法之前將支持的字符串映射到表達式。
我還沒有測試過上面的代碼,但希望它能讓你走上正軌。你試圖做的並不是一件容易的事,所以要對自己有耐心。
祝你好運。