SQLite.net SQLiteFunction 在 Linq to SQL 中不起作用

问题描述 投票:0回答:2

我使用 System.Data.SQLite.SQLiteFunction 在 C# 中创建了一些自定义 SQLite 函数。当使用 SQLiteDataAdapter 执行查询时,它工作得很好,它不起作用,但是,当使用 Linq to SQL 时,我收到错误,指出该函数不存在

我想底线是,如何让自定义 SQLiteFunctions 在 Linq to SQL 中工作?要么让它们按照预期的方式加载,要么修改 SQLite.Net 的源代码,使它们成为一部分dll的?

注意:我知道实体框架是首选,这是遗留应用程序,我没有选择更改它。我尝试将函数手动绑定到 DataContext.Connection,没有骰子。


有关尝试修改 System.Data.SQLite 的背景: 我尝试下载源代码,我可以从源代码成功构建,但源代码对我来说有点令人困惑。

  • 在System.Data.SQLite.2012项目中,项目中没有包含任何文件,但所有源文件都存在于实际文件夹中。它们似乎包含在解决方案中名为 System.Data.SQLite.Files.targets 的文件中。这对我来说是一个奇怪的设置。
  • 我将自定义函数添加到项目文件夹中,但没有像所有其他文件一样将它们包含在项目中。然后我将它们添加到 System.Data.SQLite.Files.targets 中。
  • 我构建了解决方案,它们确实出现在程序集中。尽管我似乎可以将文件添加到程序集并构建,但修改现有代码似乎没有任何影响。
  • 我进入 SQLiteConnection 类并在 Open 方法中添加了一个 throw new Exception,我在关键位置添加了 Console.Writeline,我在现有代码中修改的任何内容似乎都无法使其进入已编译的程序集中。

这样做的目标是尝试将我的自定义函数构建到 System.Data.SQLite.dll 中,而不是依赖于通过反射自动加载。

c# sqlite linq-to-sql system.data.sqlite
2个回答
40
投票

就在那一刻,我发现了这个很好的片段来自这个问题

// 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 来完成此操作。


0
投票

我知道,迟到了,但是你不能在实际使用代码之前在代码中的某个地方调用

SQLiteFunction.RegisterFunction(typeof(RegExSQLiteFunction));
吗?

© www.soinside.com 2019 - 2024. All rights reserved.