【问题标题】:SQLite.net SQLiteFunction not working in Linq to SQLSQLite.net SQLiteFunction 在 Linq to SQL 中不起作用
【发布时间】:2014-08-05 10:58:31
【问题描述】:

我使用 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


    【解决方案1】:

    就在那一刻,我发现了这个漂亮的 sn-p 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 的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多