2016-09-21 6 views
0

私は書籍のリストを持っていますが、各書籍にはリンクされた著者がいます。 My Apiを使用すると、ユーザーはタイトルまたは著者のいずれかで検索できます。 APIでLinqはリストとリンクされたプロパティを検索します

私は、検索モデルを持っている

public class SearchOptions 
{ 
    public string Title { get; set; } 
    public string Author { get; set; } 
} 

ユーザーは、両方のフィールドまたは単にタイトルまたは単に作者を使用することができます。ここで

は、それは私が戻ってすべての結果を取得し、空白文字列のIE作者が完了していないときので、私は、次のLINQクエリが、その非常に適切ではないが作成されました私の私の本と著者モデル

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; } 
} 

です。

私は文字列がnullでも空でもなく、作成者(そしてタイトルと同じ)にフィルタを適用するとほとんど言いたいのですが、Linqでこれをどうやって行うのか分かりませんか?

var returnedBooks = _bookRepository.GetAll() 
      .Where(x => x.Title.Contains(title) || 
      (x.LinkedAuthor.FirstName + " " + x.LinkedAuthor.LastName).Contains(authorName)).ToList(); 
+1

可能な複製を[ Linqオプションのパラメータ](http://stackoverflow.com/questions/10031067/linq-optional-parameters) – ASh

+0

search-titleまたはsearch-autorがString.Emptyの場合、わからない何か?もしそうなら、照会の前に平文 'if'でこれを扱わないのはなぜですか? 'Enumerable.Empty ()'を返すことができます。 –

+0

'_bookRepository'とは何ですか?' GetAll() 'は何を返しますか?それがIQueryableでない限り、関連する結果のみを返すクエリを実行するのではなく、データベースからすべてをメモリにロードする厄介なバグがあります。次に、各著者フィールドを個別に検索してみませんか?そうであるように、各著者のために新しい一時的な文字列を生成します。クエリがデータベースにヒットした場合、インデックス作成の利点も失われます –

答えて

2

あなたは、プロパティ一つ一つの値をチェックすることで、クエリのどこの部分を作成することができます。ユーザーがタイトルを入力した場合は、このプロパティのフィルタを追加します。ユーザーが作成者の名前を入力した場合、そのようにフィルタを追加し、...

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)); 
} 
+0

ダブル 'Where'呼び出しの結果は、' OR'の代わりに 'AND'になります。あなたはFirstName *と* LastNameに著者の名前が表示されるように求めています。 'x.LinkedAuthor.FirstName.Contains(authorName)||を使うべきです。 x.LinkedAuthor.LastName.Contains(authorName) ' –

+0

@PanagiotisKanavosは同意します、ありがとうございます。 –

0
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(); 
+1

まず、答えが何であるかを説明するコードなしの回答はあまり役に立ちません。第二に、他人が実際にそれを読むことができるようにコードをフォーマットする必要があります。最後に 'let fullName = a.LinkedAuthor.FirstName +" "+ a.LinkedAuthor.LastName'節を' where'の前に連結解除することができます。これにより、同じ文字列を2回生成することも回避されます –

0

あなたは、各クエリ用語をチェックし、句がそれに基づいて場所を構築することができます。 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)); 

また、あなたが構築節のこのタイプのためのIQueryableを返すリポジトリ_bookRepository.GetQueryable()でメソッドを実装していることを確認してください:SearchOptions(あなたのクエリ用語を含む) -

私はあなたの要求モデルを受け取ると仮定します。

そして、何あなたがして実装しますが、次のされて:あなたはここを読むことができ

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 

https://softwareengineering.stackexchange.com/questions/192044/should-repositories-return-iqueryable

とダイナミック句に1つの以上の参照:のHow do I implement a dynamic 'where' clause in LINQ?

関連する問題