C# 使用Contains在非英语文本的SQLite中搜索返回的结果比预期的多
我在WPF应用程序中使用Sqlite+EF,当我在数据库中搜索包含非英语字母的文本时,我得到了我期望的行+另一行不知道它为什么出现。 我所做的是:C# 使用Contains在非英语文本的SQLite中搜索返回的结果比预期的多,c#,wpf,sqlite,entity-framework-6,C#,Wpf,Sqlite,Entity Framework 6,我在WPF应用程序中使用Sqlite+EF,当我在数据库中搜索包含非英语字母的文本时,我得到了我期望的行+另一行不知道它为什么出现。 我所做的是: dbContext.MyTable.Where(w=>w.Name.Contains(someNonEnglishTextHere)) DB是Sqlite3 编码是UTF-8 MyTable中的列Name具有CollateasNOCASE 我用的是EF6 当查看EF形成的sql查询时,包含由CHARINDEX重新计算的而不是LIKE,有没有办法强
dbContext.MyTable.Where(w=>w.Name.Contains(someNonEnglishTextHere))
- DB是Sqlite3
- 编码是UTF-8
中的列MyTable
具有Name
asCollate
NOCASE
- 我用的是EF6
当查看EF形成的sql查询时,
包含由CHARINDEX
重新计算的而不是LIKE
,有没有办法强制EF使用LIKE
?如果我能做到的话,也许这就是解决方案。您可以通过注入db拦截器来重放CHARINDEX函数。
将拦截器添加到dbcontext
class MyDBContext: DbContext
{
static MyDBContext()
{
DbInterception.Add(new SqliteInterceptor());
}
}
像这样完成拦截器:
class SqliteInterceptor : IDbCommandInterceptor
{
private static Regex replaceRegex = new Regex(@"\(CHARINDEX\((.*?),\s?(.*?)\)\)\s*?>\s*?0");
public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
}
public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
}
public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
}
public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
ReplaceCharIndexFunc(command);
}
public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
}
public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
ReplaceCharIndexFunc(command);
}
private void ReplaceCharIndexFunc(DbCommand command)
{
bool isMatch = false;
var text = replaceRegex.Replace(command.CommandText, (match) =>
{
if (match.Success)
{
string paramsKey = match.Groups[1].Value;
string paramsColumnName = match.Groups[2].Value;
//replaceParams
foreach (DbParameter param in command.Parameters)
{
if (param.ParameterName == paramsKey.Substring(1))
{
param.Value = string.Format("%{0}%", param.Value);
break;
}
}
isMatch = true;
return string.Format("{0} LIKE {1}", paramsColumnName, paramsKey);
}
else
return match.Value;
});
if (isMatch)
command.CommandText = text;
}
}
类SqliteInterceptor:IDBComandInterceptor
{
私有静态正则表达式replaceRegex=新正则表达式(@“\(CHARINDEX\(.*?\s?(.*?)\)\s*?>\s*?0”);
public void NonQueryExecuted(DbCommand命令,DbCommandInterceptionContext interceptionContext)
{
}
public void非查询执行(DbCommand命令,DbCommandInterceptionContext interceptionContext)
{
}
public void ReaderExecuted(DbCommand命令,DbCommandInterceptionContext interceptionContext)
{
}
public void reader执行(DbCommand命令,DbCommandInterceptionContext interceptionContext)
{
ReplaceCharIndexFunc(命令);
}
已执行公共空标度(DbCommand命令、DbCommandInterceptionContext interceptionContext)
{
}
public void scalare执行(DbCommand命令、DbCommandInterceptionContext interceptionContext)
{
ReplaceCharIndexFunc(命令);
}
专用void ReplaceCharIndexFunc(DbCommand命令)
{
bool-isMatch=false;
var text=replaceRegex.Replace(command.CommandText,(匹配)=>
{
如果(匹配成功)
{
字符串paramsKey=match.Groups[1]。值;
字符串paramsColumnName=match.Groups[2]。值;
//替换参数
foreach(command.Parameters中的DbParameter参数)
{
if(param.ParameterName==paramsKey.Substring(1))
{
param.Value=string.Format(“%{0}%”,param.Value);
打破
}
}
isMatch=true;
返回string.Format(“{0}类似于{1}”,paramsColumnName,paramsKey);
}
其他的
返回match.Value;
});
如果(isMatch)
command.CommandText=文本;
}
}
我通过重写函数解决了问题
[SQLiteFunction(Arguments = 1, FuncType = FunctionType.Scalar, Name = "Lower")]
class CustomLower : SQLiteFunction
{
public override object Invoke(object[] args)//characters for the growth of
{
return args[0].ToString().ToLower();
}
}
[SQLiteFunction(Arguments = 2, FuncType = FunctionType.Scalar, Name = "CHARINDEX")]
class CustomCharIndex : SQLiteFunction
{
public override object Invoke(object[] args)//characters for the growth of
{
return args[1].ToString().IndexOf(args[0].ToString(), StringComparison.Ordinal) + 1;
}
}
你解决了吗?我和西里尔语也有同样的问题…从来没有解决过,在内存中搜索,所以我可以摆脱在数据库中搜索。