我正在尝试向我的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
答案 0 :(得分:0)
这不是您的答案,但是当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 :(得分:0)
我发现了问题。尝试捕获无法正常工作,我将其删除,并立即收到一个异常消息:“返回的结果不能小于1”或类似的内容。因此,基本上因为该行,结果至少需要1行以上。
ORDER BY UserId OFFSET @PageSize*(@PageIndex-1) ROWS FETCH NEXT
@PageSize ROWS ONLY;
因此,我添加了一个条件,该条件首先检查结果大小,如果结果为零而不是使用上面的存储过程返回,我只是返回了一个空列表。
答案 2 :(得分:0)
您的存储过程是一个简单的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内部产生)。
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();