Reputation: 1443
I have a list of Books, each book has a linked Author. My Api allows a user to search either by Title or Author.
In the Api i have a search Model
public class SearchOptions
{
public string Title { get; set; }
public string Author { get; set; }
}
The user may use both fields or just Title or just Author.
Here are my my Books and Author Models
public class Book
{
public string Title { get; set; }
public string Description { get; set; }
public Author LinkedAuthor { get; set; }
}
public class AuthorEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
I've created the following Linq query but its not quite right because when the author is not completed i.e. it's a blank string i get all the results back.
I almost want to say if the string is not null or empty then apply the filter for author (and the same with the title) but I'm not sure how to do this in Linq?
var returnedBooks = _bookRepository.GetAll()
.Where(x => x.Title.Contains(title) ||
(x.LinkedAuthor.FirstName + " " + x.LinkedAuthor.LastName).Contains(authorName)).ToList();
Upvotes: 0
Views: 538
Reputation: 26645
You can create where part of the query by checking values of the properties one by one. If user entered any title, then add filter for this property. If user entered name of the author, then add filter and so on...
var books = _bookRepository.GetAll();
if (!String.IsNullOrEmpty(title))
books = books.Where(x => x.Title.Contains(title));
if (!String.IsNullOrEmpty(authorName))
{
books = books.Where(x => x.LinkedAuthor.FirstName.Contains(authorName) || x.LinkedAuthor.LastName.Contains(authorName));
}
Upvotes: 2
Reputation: 2978
var returnedBooks =
from a in _bookRepository.GetAll()
where (
a.Title.Contains(title)) ||
((a.LinkedAuthor.FirstName + " " + a.LinkedAuthor.LastName) != null
&& (a.LinkedAuthor.FirstName + " " + a.LinkedAuthor.LastName).Contains(authorName)
)
select a)
.ToList();
Upvotes: 0
Reputation: 12452
You can check each query term and construct where clause based on them.
I assume you receive a request model - SearchOptions (with your query terms) : searchOptions
var books = _bookRepository.GetAll();
if (!string.IsNullOrEmpty(searchOptions.Title))
books = books.Where(x.Title.Contains(searchOptions.Title));
if (!string.IsNullOrEmpty(searchOptions.AuthorName))
books = books.Where((x.LinkedAuthor.FirstName + " " + x.LinkedAuthor.LastName).Contains(searchOptions.AuthorName));
Also make sure that you implement a method in your repository _bookRepository.GetQueryable()
returning IQueryable for this type of constructed where clauses.
And what you'll implement then is the following:
var query = _bookRepository.GetQueryable();
if (!string.IsNullOrEmpty(searchOptions.Title))
query = query.Where(x.Title.Contains(searchOptions.Title));
if (!string.IsNullOrEmpty(searchOptions.AuthorName))
query = query.Where((x.LinkedAuthor.FirstName + " " + x.LinkedAuthor.LastName).Contains(searchOptions.AuthorName));
var books = query.ToList(); // or i don't know, just enumerate
You can read more here: https://softwareengineering.stackexchange.com/questions/192044/should-repositories-return-iqueryable
And one more reference for dynamic where clauses: How do I implement a dynamic 'where' clause in LINQ?
Upvotes: 0