前提・実現したいこと
メールアドレスの一部を検索条件として、条件に合致する人を抽出するシステムを.NET Coreにて開発しようとしています。
DB(テーブル定義とデータ例)と検索の仕様(AND条件/OR条件)は以下の通りです。
■ DB(テーブル定義とデータ例)
・「Person」テーブル
Id (主キー,整数型) | Name (文字列型) |
---|---|
1 | 山田 一郎 |
2 | 田中 二郎 |
3 | 鈴木 三郎 |
4 | 佐藤 四郎 |
・「Email」テーブル … Person.IdとEmail.PersonIdが1:nで紐付く
Id (主キー,整数型) | PersonId (外部キー,整数型) | Address (文字列型) |
---|---|---|
1 | 1 | yamada@yahoo.co.jp |
2 | 1 | yamada@google.com |
3 | 2 | tanaka@yahoo.co.jp |
4 | 2 | tanaka@google.com |
5 | 2 | tanaka@outlook.jp |
6 | 3 | suzuki@yahoo.co.jp |
7 | 3 | suzuki@outlook.jp |
8 | 4 | satou@google.com |
9 | 4 | satou@outlook.jp |
意味としては、「何人かの人がいて、1人が複数のメールアドレスを持っている」というものとなります。
■ 検索の仕様(AND条件)
検索条件となる文字列がList<string>
形式で検索用メソッドにに渡されます。
「メールアドレスが、Listに含まれる全ての文字列と部分一致する人」を抽出したいです。
(例) 検索条件が["yahoo", "outlook"]
の場合
…「"yahoo"が含まれるメールアドレスと"outlook"が含まれるメールアドレスの両方を持つ人」を検索する。
上記のデータ例の場合、「田中 二郎」さんと「鈴木 三郎」さんがヒットする。
■ 検索の仕様(OR条件)
検索条件となる文字列がList<string>
形式で検索用メソッドにに渡されます。
「メールアドレスが、Listに含まれる文字列のいずれかと部分一致する人」を抽出したいです。
(例) 検索条件が["yama", "google"]
の場合
…「"yama"か"google"のいずれかが含まれるメールアドレスを持つ人」を検索する。
上記のデータ例の場合、「山田 一郎」・「田中 二郎」・「佐藤 四郎」さんがヒットする。
発生している問題
上記の検索をEntity FrameworkとLINQにて実装しようとしていますが、実装方法が思い付かず、進められない状況です。
データが大量になる可能性があることから、DBからデータを取得してきてから加工する方法は極力避けたいと考えています。
クエリの具体的な実装をご教示いただけますと幸いです。
該当のソースコード
モデル定義は下記の通りです。
C#
1// 人モデル 2public class Person { 3 public int Id { get; set; } 4 public string Name { get; set; } 5 6 // メールを複数持つ 7 public ICollection<Email> Email { get; set; } 8} 9 10// メールモデル 11public class Email { 12 public int Id { get; set; } 13 public int PersonId { get; set; } 14 public string Address { get; set; } 15 16 public Person Person { get; set; } 17}
DBコンテキストの実装について記載はここでは省略します。
検索処理は下記の通りです。
C#
1// AND検索用メソッド 2public List<Person> SearchAnd(List<string> searchWords) 3{ 4 // 「context」の中身は別途用意済みのDbContext。 5 var qPerson = this.context.Person; 6 7 if (searchWords != null && searchWords.Any()) 8 { 9 // qPerson = ***** という形式で、 10 // ここでAND検索を行いたい。 11 // DB上に大量のレコードがあっても問題が起きないよう、 12 // ここでの絞り込み中にクエリが実行されないようにしたい。 13 } 14 15 // ToList()によって、クエリを実行させつつList化して返す。 16 return qPerson.ToList(); 17} 18 19 20// OR検索用メソッド 21public List<Person> SearchOr(List<string> searchWords) 22{ 23 // 「context」の中身は別途用意済みのDbContext。 24 var qPerson = this.context.Person; 25 26 if (searchWords != null && searchWords.Any()) 27 { 28 // qPerson = ***** という形式で、 29 // ここでOR検索を行いたい。 30 // DB上に大量のレコードがあっても問題が起きないよう、 31 // ここでの絞り込み中にクエリが実行されないようにしたい。 32 } 33 34 // ToList()によって、クエリを実行させつつList化して返す。 35 return qPerson.ToList(); 36}
試したこと
OR条件の検索については以下の実装を試しましたが、実行時エラーとなりました。
C#
1 qPerson = qPerson.Where( p => 2 p.Emails.Any( em => 3 searchWords.Any( w => 4 em.Address.Contains(w) 5 ) 6 ) 7 );
実行時に発生するエラーはSystem.InvalidOperationExceptionです。
' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
AND条件の方については、実装方法が思い付いていない状況です。
補足情報(FW/ツールのバージョンなど)
.NET Coreのバージョン:3.1.0
Entity Framework Coreのバージョン:3.1.1
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/02/19 02:50