我正在构建一个WinForms应用程序,该应用程序在数据库中搜索书籍。
我有四个表: 作者,图书,国家/地区,类型;
“书”表中有一个名为“年份”的字段。 我添加了 startDate 和 endDate 字段,因此它可以搜索在给定的两年之间发行的特定书籍(startDate和endDate都是整数)。这就是我的麻烦开始的地方。
这就是我解析输入的方式。
int startDateResult = 0;
int? startDate = null;
if (inputStartDate == string.Empty)
{
startDate = null;
}
else
{
if (Int32.TryParse(inputStartDate, out startDateResult))
{
startDate = startDateResult;
}
else throw new Exception("Please input correct year");
}
int endDateResult = 0;
int? endDate = null;
if (inputEndDate == string.Empty)
{
endDate = null;
}
else
{
if (Int32.TryParse(inputEndDate, out endDateResult))
{
endDate = endDateResult;
}
else throw new Exception("Please input correct year");
}
这是我用于搜索的LINQ查询。
specificBookForAuthor = _context.Books.Where(c =>
(c.Author.Name.Contains(First) || c.Author.Surname.Contains(Last))
&& book==string.Empty?true: c.Name.Contains(book)
&& country == string.Empty ? true : c.Author.Country.Name.Contains(country)
&& genre == string.Empty ? true : c.Genre.Name.Contains(genre)
&& inputYear == string.Empty ? true : c.Year==year
&& inputStartDate == string.Empty ? true : c.Year >= startDate
&& inputEndDate == string.Empty ? true : c.Year <= endDate
).Select(b => b).ToList();
此查询无效。然后,我尝试注释除“ inputEndDate”以外的所有行,在startDate中键入0,在endDate中键入5000。调试后,发现“ specificBookAuthor”的计数为1。这是正确的。
注释代码:
specificBookForAuthor = _context.Books.Where(c =>
(c.Author.Name.Contains(First) || c.Author.Surname.Contains(Last))
//&& book==string.Empty?true: c.Name.Contains(book)
//&& country == string.Empty ? true :
// c.Author.Country.Name.Contains(country)
// && genre == string.Empty ? true : c.Genre.Name.Contains(genre)
// && inputYear == string.Empty ? true : c.Year==year
// && inputStartDate == string.Empty ? true : c.Year >= startDate
inputEndDate == string.Empty ? true : c.Year <= endDate
).Select(b => b).ToList();
与inputStartDate(注释inputEndDate行和未注释inputInputDate)相同。很好
当我不评论两个字段时我遇到了问题。像这样:
specificBookForAuthor = _context.Books.Where(c =>
(c.Author.Name.Contains(First) || c.Author.Surname.Contains(Last))
//&& book==string.Empty?true: c.Name.Contains(book)
//&& country == string.Empty ? true :c.Author.Country.Name.Contains(country)
// && genre == string.Empty ? true : c.Genre.Name.Contains(genre)
// && inputYear == string.Empty ? true : c.Year==year
&& inputStartDate == string.Empty ? true : c.Year >= startDate
&& inputEndDate == string.Empty ? true : c.Year <= endDate
).Select(b => b).ToList();
在这种情况下,“ specificBookAuthor”的计数为NULL而不是1。
答案 0 :(得分:2)
您能否测试可能与问题不直接相关的以下更改,但可以为您提供更具可读性/可调试性的代码?
将代码重写为此:
specificBookForAuthor = _context.Books.Where(c =>
(c.Author.Name.Contains(First) || c.Author.Surname.Contains(Last)));
if(!string.IsNullOrEmpty(book))
specificBookForAuthor = specificBookForAuthor.Where(c => c.Name.Contains(book));
if(!string.IsNullOrEmpty(country))
specificBookForAuthor = specificBookForAuthor.Where(c => c.Author.Country.Name.Contains(country));
//....and so on with your other conditions;
//....finally:
specificBookForAuthor = specificBookForAuthor.ToList();
正如我所说,这可能无法解决您的问题,但是通过这种方式,您可以逐个条件正确调试条件,也许然后您就可以找到问题了。
答案 1 :(得分:0)
因此,每个Book
都有一个属性Year
,代表书籍出版的年份。
此外,您有两个可为空的整数startDate
和endDate
,并且您希望将所选图书限制为在startDate
和endDate
之间出版的图书,特殊情况下,如果一个或多个这两个值都为空。
您有一个输入IQueryable<Book>
,作为输出,您希望查询仅获取startDate
和endDate
之间的书,如果这些值为空,则进行特殊处理。
为了保持可读性,可测试性和可维护性,我建议使用扩展功能。参见Extension Methods Demystified
public static IQueryable<Book> WherePublishedBetween(this IQueryable<Book> books,
Year? start,
Year? end)
{
if (start.HasValue)
{
if (end.HasValue)
return books.Where(book => start.Value <= book.Year && book.Year <= end.Value);
else
return books.Where(book => start.Value <= book.Year);
}
else
{ // no start value
if (end.HasValue)
return books.Where(book => book.Year <= end.Value);
else
return books;
}
}
用法:
int? startYear = ...
int? endYear = ...
var queryBooks = myDbContext.Books
.Where(book => book.Author.Name.Contains(First)
|| book.Author.Surname.Contains(Last)
&& ... // check other properties)
.WherePublishedBetween(startYear, endYear)
// continue with the query, with whatever LINQ you need
.Select(book => ...)
LINQ表达式构建器将足够聪明,可以使用Expression.AndAlso组合这两个Where
语句