我使用System.Data.SQLite.SQLiteFunction在C#中创建了一些自定义SQLite函数。使用SQLiteDataAdapter执行查询时效果很好,它不起作用,但是,当使用Linq to SQL时,我收到错误声明该函数不存在。
我想底线是,如何让Custom SQLiteFunctions在Linq to SQL中工作?要么让它们加载它们应该的方式,要么修改源代码SQLite.Net所以他们是dll的一部分吗?
注意:我理解实体框架是首选,这是遗留应用程序,我无法更改此选项。我尝试手动将函数绑定到DataContext.Connection,没有骰子。
有关尝试修改System.Data.SQLite的背景知识: 我尝试下载源代码,我可以从源代码成功构建,但源代码对我来说有点令人费解。
这样做的目的是尝试将自定义函数构建到System.Data.SQLite.dll中,而不是依赖于通过反射自动加载。
答案 0 :(得分:27)
就在那一刻,我发现了这个不错的代码段from this question
// from https://stackoverflow.com/questions/172735/create-use-user-defined-functions-in-system-data-sqlite
// taken from http://sqlite.phxsoftware.com/forums/p/348/1457.aspx#1457
[SQLiteFunction(Name = "REGEXP", Arguments = 2, FuncType = FunctionType.Scalar)]
public class RegExSQLiteFunction : SQLiteFunction {
public override object Invoke(object[] args) {
return System.Text.RegularExpressions.Regex.IsMatch(Convert.ToString(args[1]), Convert.ToString(args[0]));
}
}
但是没有找到如何使用它。现在有一个SQLiteConnection.BindFunction方法。它很难看,所以我做了一个小扩展方法:
public static void BindFunction(this SQLiteConnection connection, SQLiteFunction function)
{
var attributes = function.GetType().GetCustomAttributes(typeof(SQLiteFunctionAttribute), true).Cast<SQLiteFunctionAttribute>().ToArray();
if (attributes.Length == 0) {
throw new InvalidOperationException("SQLiteFunction doesn't have SQLiteFunctionAttribute");
}
connection.BindFunction(attributes[0], function);
}
现在你必须
using (var connection = new SQLiteConnection( "Data Source=YourDB.sqlite" ))
{
connection.Open(); // Connection must be open to bind a function
connection.BindFunction(new RegExSQLiteFunction());
// Here create a command, and try REGEXP, for example
// SELECT * FROM "table" WHERE "column" REGEXP '(?i)\btest\b'
// looks for the word 'test', case-insensitive in a string column
}
现在你如何在LINQ to SQL中做到这一点,我不知道因为我在LINQ IQueryProvider上拥有自己的SQL。这是使用基本IDbConnection,IDbCommand,IDbDataParameter和IDataReader接口以及自定义SQLiteFunction的方法。