LINQ-запрос пуст - PullRequest
       2

LINQ-запрос пуст

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

Я создаю приложение 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», набрал 0 в startDate и 5000 в endDate.После отладки выяснилось, что число «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 и незакомментированная inputStartDate).Работал нормально.

Проблема возникает, когда я оставляю оба поля без комментариев.Например:

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 голосов
/ 15 октября 2018

Таким образом, у каждого Book есть свойство Year, представляющее год, в котором книга была издана.

Кроме того, у вас есть два целых числа, допускающих обнуление startDate и endDate, и вы хотите ограничитьот выбранных книг до книг, опубликованных между startDate и endDate, в особых случаях, если одно или оба из этих значений равны нулю.

У вас есть входные данные IQueryable<Book> и в качестве выходных данных вы хотите запрос, который будет толькоизвлекайте книги в диапазоне от startDate до endDate, особенно если эти значения равны нулю.

Чтобы сделать его читабельным, тестируемым и поддерживаемым, я предлагаю функцию расширения.См. Расширение методов расширения

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 будет достаточно умен, чтобы объединить эти два оператора Where, используя Expression.AndAlso

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

Не могли бы вы проверить следующее изменение, которое может не иметь непосредственного отношения к проблеме, но может дать вам более читаемый / отлаживаемый код?

Перепишите свой код так:

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(); 

Как я уже сказал, это может не решить вашу проблему, но таким образом вы сможете правильно отладить условие по условию и, возможно, тогда вы сможете найти проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...