Entity Framework Coreでフルテキスト検索を実装します。
概要
SQL Serverでは、ContainsやFreetextを利用したSQLを実行して、フルテキストインデックスを利用したフリーテキスト検索が利用できます。
Entity Framework Coreでもフルテキスト検索を実行したい場合がありますが、Entity Framework Coreでは直接SQL文を実行する方法は主流ではないため、
LINQのクエリ構文やメソッド構文でフリーテキスト検索を実行したいです。
この記事では、Entity Framework Coreでフルテキスト検索するコードを紹介します。
書式
Microsoft.EntityFrameworkCore.EF
クラスの
Functions.Contains()
メソッド、
Functions.FreeText()
メソッドを利用します。
Contains
where Microsoft.EntityFrameworkCore.EF.Functions.Contains([検索対象列], [検索クエリ])
.Where(e => EF.Functions.Contains([検索対象列], [検索クエリ])
FreeText
where Microsoft.EntityFrameworkCore.EF.Functions.FreeText([検索対象列], [検索クエリ])
.Where(e => EF.Functions.FreeText([検索対象列], [検索クエリ])
テーブルの準備
以下のテーブルを準備します。
Working テーブルid | name | value | category | memo |
1 | Penguin | 300 | B | 南国にすむペンギンです |
2 | Whale | 420 | M | 北極海のクジラです |
3 | Moffu | 880 | NULL | よくわからない生き物です |
4 | Camel | 220 | M | 砂漠にすむラクダです |
5 | Owl | 90 | B | 関東のフクロウです |
6 | Duck | 120 | B | そこらへんのアヒルです |
7 | Lizard | 60 | R | ひっそりと生きるトカゲです |
DbContextの作成
Scaffold-DbContextコマンドを使用して、Entity Framework CoreのDbContextを作成します。
手順の詳細は
こちらの記事を参照してください。
プログラム
UI
下図のフォームを作成します。1行のテキストボックスを1つ、複数行(Multilineプロパティ=true)のテキストボックスを1つ、ボタンを2つ配置します。
コード
以下のコードを記述します。
using EntityFrameworkCoreFullTextIndex.models;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.EntityFrameworkCore;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
namespace EntityFrameworkCoreFullTextIndex
{
public partial class FormContains : Form
{
public FormContains()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string my_query = textBox1.Text;
IPentecSandBoxContext ctx = new IPentecSandBoxContext();
//List<Working> result = ctx.Workings.Where(e => EF.Functions.Contains(e.Memo, my_query)).ToList();
List<Working> result = (from tbl in ctx.Workings where Microsoft.EntityFrameworkCore.EF.Functions.Contains(tbl.Memo, my_query) select tbl).ToList();
foreach (Working w in result) {
textBox2.Text += string.Format("{0:d} : {1} - {2:g} - {3}\r\n", w.Id, w.Name.Trim(), w.Value, w.Memo.Trim());
}
}
private void button2_Click(object sender, EventArgs e)
{
string my_query = textBox1.Text;
IPentecSandBoxContext ctx = new IPentecSandBoxContext();
//List<Working> result = ctx.Workings.Where(e => EF.Functions.FreeText(e.Memo, my_query)).ToList();
List<Working> result = (from tbl in ctx.Workings where Microsoft.EntityFrameworkCore.EF.Functions.FreeText(tbl.Memo, my_query) select tbl).ToList();
foreach (Working w in result) {
textBox2.Text += string.Format("{0:d} : {1} - {2:g} - {3}\r\n", w.Id, w.Name.Trim(), w.Value, w.Memo.Trim());
}
}
}
}
解説
メソッド構文で、フルテキストインデックスの Contains 検索をする場合の記述です。今回の例では、検索時にToList()メソッドを呼び出し、リスト形式で
レコードの一覧を取得しています。
List<Working> result = ctx.Workings.Where(e => EF.Functions.Contains(e.Memo, my_query)).ToList();
クエリ構文で、フルテキストインデックスの Contains 検索をする場合の記述です。今回の例では、検索時にToList()メソッドを呼び出し、リスト形式で
レコードの一覧を取得しています。
List<Working> result = (from tbl in ctx.Workings where Microsoft.EntityFrameworkCore.EF.Functions.Contains(tbl.Memo, my_query) select tbl).ToList();
メソッド構文で、フルテキストインデックスの FreeText 検索をする場合の記述です。今回の例では、検索時にToList()メソッドを呼び出し、リスト形式で
レコードの一覧を取得しています。
List<Working> result = ctx.Workings.Where(e => EF.Functions.FreeText(e.Memo, my_query)).ToList();
クエリ構文で、フルテキストインデックスの FreeText 検索をする場合の記述です。今回の例では、検索時にToList()メソッドを呼び出し、リスト形式で
レコードの一覧を取得しています。
List<Working> result = (from tbl in ctx.Workings where Microsoft.EntityFrameworkCore.EF.Functions.FreeText(tbl.Memo, my_query) select tbl).ToList();
実行結果
プロジェクトを実行します。
ウィンドウが表示されますので、上部のテキストボックスに検索ワードを入力します。
[button1]をクリックします。Memoフィールドを検索して検索ワードが含まれる項目を表示します。
別の検索ワードでも試してみます。
該当する項目が複数ある場合は、複数件表示されます。
[button2]をクリックして、FreeTextでの検索結果です。こちらも動作しています。
補足: 複数語句、検索語句を空で実行した場合の動作
空文字列で実行した場合
検索文字列を空にして[button1]または[button2]をクリックします。
以下の例外が発生します。
エラーメッセージ
Microsoft.Data.SqlClient.SqlException
HResult=0x80131904
Message=フルテキスト述語が NULL または空です。
Source=Core Microsoft SqlClient Data Provider
スタック トレース:
......
複数語句で実行した場合
検索文字列を "海 クジラ" を設定して[button1]をクリックします。
以下の例外が発生します。
エラーメッセージ
Microsoft.Data.SqlClient.SqlException
HResult=0x80131904
Message=フルテキスト検索条件 '海 クジラ' の 'クジラ' 付近で構文エラーが発生しました。
Source=Core Microsoft SqlClient Data Provider
スタック トレース:
......
なお、[button2]の場合は、検索結果が表示できます。
検索文字列は、CONTAINS, FREETEXT句にそのまま渡されるため、CONTAINS句での検索をする場合には、"AND" や "OR" 演算子を追加する必要があります。
検索文字列を、"海 AND クジラ" に設定して、[button1]をクリックすると、検索結果のレコードが取得できます。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2023-06-27
作成日: 2023-06-26