Entity Framework Core でフルテキスト検索を実行すると、つぎの例外が発生し動作しない現象と対処法を紹介します。
- 「Microsoft.Data.SqlClient.SqlException: 引数の型 "ntext" は、"CONTAINS" の引数 2 には無効です。」
- 「Microsoft.Data.SqlClient.SqlException: 引数の型 "ntext" は、"FREETEXT" の引数 2 には無効です。」
現象の確認
テーブル
以下のテーブルを準備します。
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 | ひっそりと生きるトカゲです |
プログラム
プロジェクトを作成し、Scaffold-DbContextコマンドを使用して、Entity Framework CoreのDbContextを作成します。
作成後以下のプログラムを作成します。
UI
下図のフォームを作成します。
コード
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 = (from tbl in ctx.Workings where Microsoft.EntityFrameworkCore.EF.Functions.Contains(tbl.Memo, my_query) select tbl).ToList();
/*
//メソッド構文
List<Working> result = ctx.Workings.Where(e => EF.Functions.Contains(e.Memo, my_query)).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 = (from tbl in ctx.Workings where Microsoft.EntityFrameworkCore.EF.Functions.FreeText(tbl.Memo, my_query) select tbl).ToList();
/*
//メソッド構文
List<Working> result = ctx.Workings.Where(e => EF.Functions.FreeText(e.Memo, my_query)).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());
}
}
}
}
プロジェクトを実行して、[button1]または[button2]をクリックすると以下の例外が発生します。
[button1]をクリックしContains関数を実行した場合の例外は以下となります。
エラーメッセージ
Microsoft.Data.SqlClient.SqlException
HResult=0x80131904
Message=引数の型 "ntext" は、"CONTAINS" の引数 2 には無効です。
Source=Core Microsoft SqlClient Data Provider
スタック トレース:
...
[button2]をクリックし、FreeText関数を実行した場合は以下の例外が発生します。
エラーメッセージ
Microsoft.Data.SqlClient.SqlException
HResult=0x80131904
Message=引数の型 "ntext" は、"FREETEXT" の引数 2 には無効です。
Source=Core Microsoft SqlClient Data Provider
スタック トレース:
...
原因
Entity Framework Coreで
text
型
ntext
型の列でフルテキスト検索を実行していることが原因と考えられます。
対処法
フルテキスト検索対象の列を text,ntext型から、varchar(MAX), nvarchar(MAX) に変更します。
テーブルデザイナで列の肩を確認すると、ntext型で定義されています。
列の型をnvarchar(MAX) に変更します。
テーブルのデータ型を変更後に再度、Scaffold-DbContextコマンドを使用してDbContextを更新します。
実行結果
プロジェクトを実行します。ウィンドウが表示されますので、上部のテキストボックスに検索ワードを入力し、[button1]または、[button2]をクリックします。
検索結果が下部のテキストボックスに表示され、フルテキスト検索が実行できたことが確認できます。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2023-06-26
作成日: 2023-06-26