LINQ查询为空

时间:2018-10-14 18:18:53

标签: c# winforms linq

我正在构建一个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。

2 个答案:

答案 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,代表书籍出版的年份。

此外,您有两个可为空的整数startDateendDate,并且您希望将所选图书限制为在startDateendDate之间出版的图书,特殊情况下,如果一个或多个这两个值都为空。

您有一个输入IQueryable<Book>,作为输出,您希望查询仅获取startDateendDate之间的书,如果这些值为空,则进行特殊处理。

为了保持可读性,可测试性和可维护性,我建议使用扩展功能。参见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语句