我試圖讓頁面查詢正常使用LINQ和NHibernate。在一張桌子上,這是完美的,但是當多個桌子結合在一起時,這會導致我大失所望。這是我到目前爲止。NHibernate的 - LINQ查詢使用COUNT(DISTINCT)
public virtual PagedList<Provider> GetPagedProviders(int startIndex, int count, System.Linq.Expressions.Expression<Func<Record, bool>> predicate) {
var firstResult = startIndex == 1 ? 0 : (startIndex - 1) * count;
var query = (from p in session.Query<Record>()
.Where(predicate)
select p.Provider);
var rowCount = query.Select(x => x.Id).Distinct().Count();
var pageOfItems = query.Distinct().Skip(firstResult).Take(count).ToList<Provider>();
return new PagedList<Provider>(pageOfItems, startIndex, count, rowCount);
}
我遇到了一些問題。首先,rowCount變量在具有一對多連接的連接上拉回一個COUNT(*)。所以我的計數是應該的,我期待129,但回到1K以上。
我正在發生的第二個問題是結果。如果我在第一頁(firstResult = 0),那麼我會得到正確的結果。但是,如果firstResult不是0,它會生成完全不同的SQL。下面是兩種情況下生成的SQL,我已經刪除了一些脂肪,使其更具可讀性。
--firstResult = 0
select distinct TOP (30) provider1_.Id as Id12_, provider1_.TaxID as TaxID12_,
provider1_.Facility_Name as Facility5_12_, provider1_.Last_name as Last6_12_,
provider1_.First_name as First7_12_, provider1_.MI as MI12_
from PPORecords record0_ left outer join PPOProviders provider1_ on record0_.Provider_id=provider1_.Id,
PPOProviders provider2_ where record0_.Provider_id=provider2_.Id
and provider2_.TaxID='000000000'
--firstResult = 30
SELECT TOP (30) Id12_, TaxID12_, Facility5_12_, Last6_12_, First7_12_, MI12_,
FROM (select distinct provider1_.Id as Id12_, provider1_.TaxID as TaxID12_,
provider1_.Facility_Name as Facility5_12_,
provider1_.Last_name as Last6_12_,
provider1_.First_name as First7_12_,
provider1_.MI as MI12_,
ROW_NUMBER() OVER(ORDER BY CURRENT_TIMESTAMP) as __hibernate_sort_row
from PPORecords record0_ left outer join PPOProviders provider1_ on record0_.Provider_id=provider1_.Id,
PPOProviders provider2_
where record0_.Provider_id=provider2_.Id and provider2_.TaxID='000000000') as query
WHERE query.__hibernate_sort_row > 30
ORDER BY query.__hibernate_sort_row
第二個查詢的問題是「distinct」關鍵字不存在於外部查詢中,只存在於內部查詢中。任何想法如何糾正這一點?
感謝您的任何建議!
[UPDATE]
這是構建LINQ查詢謂詞的代碼。
private Expression<Func<Record, bool>> ParseQueryExpression(string Query) {
Expression<Func<Record, bool>> mExpression = x => true;
string[] splitQuery = Query.Split('|');
foreach (string query in splitQuery) {
if (string.IsNullOrEmpty(query))
continue;
int valStartIndex = query.IndexOf('(');
string variable = query.Substring(0, valStartIndex);
string value = query.Substring(valStartIndex + 1, query.IndexOf(')') - valStartIndex - 1);
switch (variable) {
case "tax":
mExpression = x => x.Provider.TaxID == value;
break;
case "net":
mExpression = Combine<Record>(mExpression, x => x.Network.Id == int.Parse(value));
break;
case "con":
mExpression = Combine<Record>(mExpression, x => x.Contract.Id == int.Parse(value));
break;
case "eff":
mExpression = Combine<Record>(mExpression, x => x.Effective_Date >= DateTime.Parse(value));
break;
case "trm":
mExpression = Combine<Record>(mExpression, x => x.Term_Date <= DateTime.Parse(value));
break;
case "pid":
mExpression = Combine<Record>(mExpression, x => x.Provider.Id == long.Parse(value));
break;
case "rid":
mExpression = Combine<Record>(mExpression, x => x.Rate.Id == int.Parse(value));
break;
}
}
return mExpression;
}
感謝您的迴應!這種方法絕對有效,但它似乎並不喜歡我傳入的謂詞。我得到的錯誤是「值不能爲null。參數名稱:key」。 謂詞是一個linq查詢,我從MVC應用程序中的控制器動態構建。實質上,我將一個字符串解析爲一個大的linq查詢。我將使用該代碼更新上述帖子。無論如何,如果我嘗試手動插入查詢「.Where(x => x.Provider.TaxID ==」000000000「),我會得到相同的錯誤,但以下工作--- .Where((=) > pAlais.TaxID ==「000000000」) – Brosto 2011-03-08 14:52:18
剛剛更新了上面的代碼,正如你所看到的,當這個查詢被完全利用時,它可以跨越多個表格,我的「Record」表格就是將它們連接在一起的粘合劑。實際上有幾個分頁列表使用相同的方法,並採用相同的確切參數(這就是爲什麼我在一個位置創建這個linq查詢...)我不確定錯誤消息是指什麼。任何想法? – Brosto 2011-03-08 15:10:55
似乎Linq表達式並不真正支持。我的建議是通過在多個查詢中拆分查詢來降低查詢的複雜性。不幸的是,這意味着您將有更多的往返數據庫。我會更新我的答案,舉例說明我的意思。 – 2011-03-09 12:39:49