簡體   English   中英

空的linq查詢結果異常

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM