[英]Exception on empty linq query result
我正在嘗試向我的MVC應用程序添加過濾器。 我在這方面有些成功,因為如果它存在於數據庫中,我可以返回一個過濾后的值。
但是,當它不存在於數據庫中時,我希望它返回一個空列表。 因為如果結果為零,Linq應該返回空。 但是,如果由於某種原因代碼語句失敗,並且由於輸入的字段與任何數據庫條目都不匹配,我就使用try catch來捕獲任何異常,而linq查詢會陷入catch並且異常為null。
我不知道這是什么錯,它甚至不應該陷入困境。
Linq查詢:
if (attr1 == "null" && attr3 != "null" && attr2 != "null")
{
attr1 = "%";
Size = db.GetFilterResultCount(index, Size, attr1, attr2, attr3).Count();
accountlist = db.GetFilterResult(index, Size, attr1, attr2, attr3).ToList();
filteredlist.GetList = accountlist;
filteredlist.index = index;
filteredlist.size = Size;
filteredlist.totalSize = db.Accounts.Count();
filteredlist.resultSize = db.GetFilterResultCount(index, Size, attr1, attr2, attr3).Count();
}
這是我用來檢查要過濾哪個字段的許多條件之一。 但是linq查詢對於所有這些查詢都是相同的。
存儲過程:
CREATE PROCEDURE [dbo].[GetFilterResult]
@PageIndex INT,
@pageSize INT,
@attr1 nvarchar(300),
@attr2 nvarchar(300),
@attr3 nvarchar(300)
AS
Begin
SELECT Accounts.firstName, Accounts.lastName, Accounts.Email,
Accounts.dateOfBirth, Accounts.phoneNo, Countries.CountryName
FROM Accounts INNER JOIN Countries On Accounts.CountryID =
Countries.CountryID
Where (Accounts.firstName LIKE CONCAT('%', @attr1, '%') and
Accounts.lastName LIKE CONCAT('%', @attr2, '%') and Accounts.CountryID
Like CONCAT('%', @attr3, '%'))
ORDER BY UserId OFFSET @PageSize*(@PageIndex-1) ROWS FETCH NEXT
@PageSize ROWS ONLY;
END
GetFilterResultCount:
CREATE PROCEDURE [dbo].[GetFilterResult]
@PageIndex INT,
@pageSize INT,
@attr1 nvarchar(300),
@attr2 nvarchar(300),
@attr3 nvarchar(300)
AS
Begin
SELECT Accounts.firstName, Accounts.lastName, Accounts.Email,
Accounts.dateOfBirth, Accounts.phoneNo, Countries.CountryName
FROM Accounts INNER JOIN Countries On Accounts.CountryID =
Countries.CountryID
Where (Accounts.firstName LIKE CONCAT('%', @attr1, '%') and
Accounts.lastName LIKE CONCAT('%', @attr2, '%') and Accounts.CountryID
Like CONCAT('%', @attr3, '%'))
END
這不是您的答案,但是當attr1 ==“ null”時,您嘗試忽略attr1 where子句。 您可以在查詢中使用IFNULL函數
Where (Accounts.firstName LIKE CONCAT('%', IFNULL(@attr1, Accounts.firstName), '%') and
並將null傳遞給存儲過程
attr1 = null;
accountlist = db.GetFilterResult(index, Size, attr1, attr2, attr3).ToList();
我發現了問題。 嘗試捕獲無法正常工作,我將其刪除,並立即收到一個異常消息:“返回的結果不能小於1”或類似的內容。 因此,基本上由於該行,結果至少需要1行以上。
ORDER BY UserId OFFSET @PageSize*(@PageIndex-1) ROWS FETCH NEXT
@PageSize ROWS ONLY;
因此,我添加了一個條件,該條件首先檢查結果大小,如果結果為零,則不使用上述存儲過程返回結果,我只是返回了一個空列表。
您的存儲過程是一個簡單的SQL選擇。 這意味着,如果沒有項目與您的SQL WHERE匹配,則存儲過程將返回一個空列表。
您忘記告訴您使用的db
類型,尤其是db.GetFilterResult
。 您是自己制作的,還是您的db
類很聰明,它會自動知道要調用哪個存儲過程。
如果您自己創建它,它將類似於:
IEnumerable<Account> GetFilterResultCount(...)
{
try
{
var fetchedData = CallStoredProcedure();
foreach(var fetchedRow in fetchedData)
{
// use fetched data to create a new account object
Account account = new Account() {... use fetchedData }
yield return account;
}
}
catch (Exception exc)
{
// TODO: decide what to do with this exception. Log and continue?
// return empty sequence as if no Accounts where available
}
}
如果存儲過程返回空選擇或異常,則將返回空序列。 如果未選擇任何選項(非常不尋常),那么對存儲過程的調用返回null
,則應檢查null返回:
var fetchedData = CallStoredProcedure();
if (fetchedData != null)
{
foreach(var fetchedRow in fetchedData) ...
有些人不喜歡使用yield
而更喜歡僅使用LINQ(盡管LINQ內部是yield)。
try
{
var fetchedData = CallStoredProcedure();
if (fetchedData == null)
{ // nothing fetched, return empty sequence
return Enumerable.Empty<Account>();
}
else
{
return fetchedData.Select(fetchedRow => new Account() {...};
}
}
catch (Exception exc)
{ // problem fetching data, return empty sequence
return Enumerable.Empty<Account>();
}
如果您熟悉yield return
,那么我不確定LINQ解決方案是否更具可讀性/可維護性。
用法:
var accountlist = db.GetFilterResult(index, Size, attr1, attr2, attr3)
.ToList();
如果您不能更改db.GetFilterResult
,我想最好是編寫自己的
IEnumerable<Account> FetchFilterResultData(...)
{
var fetchedData = db.GetFilterResult(...);
// return emtpy sequence if null returned:
return fetchedData ?? Enummerable.Empty<Account>();
// TODO: exception handling needed?
}
用法:
var accountlist = this.FetchFilterResultData(index, Size, attr1, attr2, attr3)
.ToList();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.