Исключение для пустого результата запроса linq - PullRequest
0 голосов
/ 08 октября 2018

Я пытаюсь добавить фильтры в мое приложение MVC.Я несколько успешен в этом, потому что я могу вернуть отфильтрованное значение, если оно присутствует в БД.

Однако, когда его нет в БД, я хочу, чтобы он возвратил пустой список.Поскольку Linq должен возвращать пустой, если результаты равны нулю.однако я использовал try catch для перехвата любых исключений, если по какой-то причине операторы кода не работают, и если введенные поля не соответствуют какой-либо записи в БД, запрос linq разбивается на catch и исключение равно null.

Iпонятия не имею, что не так, это не должно быть даже в ловушку.

Запрос 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

Ответы [ 3 ]

0 голосов
/ 08 октября 2018

Я нашел проблему.Уловочный пробник не работал нормально, я удалил его и сразу же получил исключение, которое гласило: «Невозможно вернуть результат меньше 1» или что-то подобное.Так что в основном результат требовал, по крайней мере, более 1 строки, вероятно, из-за этой строки.

    ORDER BY UserId OFFSET @PageSize*(@PageIndex-1) ROWS FETCH NEXT 
 @PageSize ROWS ONLY;

поэтому я добавил условие, которое сначала проверяло размер результата и, если оно было нулевым, вместо возврата, используя хранимую процедуру выше iпросто вернул пустой список.

0 голосов
/ 08 октября 2018

Ваша хранимая процедура представляет собой простой выбор 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, если ничего не выбрано (очень необычно), вы должны проверить нулевой возврат:

 var fetchedData = CallStoredProcedure();
 if (fetchedData != null)
 {
     foreach(var fetchedRow in fetchedData) ...

Некоторые люди не любят использовать yield и предпочитают LINQ-only(хотя LINQ внутренне дает).

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();
0 голосов
/ 08 октября 2018

Это не ваш ответ, но вы пытаетесь игнорировать пункт attr1 where, когда attr1 == "null".Вы можете использовать функцию IFNULL в своем запросе

Where (Accounts.firstName LIKE  CONCAT('%', IFNULL(@attr1, Accounts.firstName), '%') and

и передать значение null хранимой процедуре

   attr1 = null;
   accountlist = db.GetFilterResult(index, Size, attr1, attr2, attr3).ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...