简体   繁体   English

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

[英]SQLite.net SQLiteFunction not working in Linq to SQL

I've created a handful of custom SQLite functions in C# using System.Data.SQLite.SQLiteFunction.我使用 System.Data.SQLite.SQLiteFunction 在 C# 中创建了一些自定义 SQLite 函数。 It works great when using SQLiteDataAdapter to execute queries, it does not work, however, when using Linq to SQL I get errors stating that the function does not exist .它在使用 SQLiteDataAdapter 执行查询时效果很好,但它不起作用,但是,当使用 Linq to SQL 时,我收到错误,指出该函数不存在

I guess the bottom line is, how can I get the Custom SQLiteFunctions to work in Linq to SQL?我想最重要的是,如何让自定义 SQLiteFunctions 在 Linq to SQL 中工作? Either by getting them to load the way they are supposed to or by modifying the source code of SQLite.Net so they are part of the dll?要么让它们按照预期的方式加载,要么通过修改 SQLite.Net 的源代码使它们成为 dll 的一部分?

Note: I understand Entity Framework is preferred, this is legacy application and I do not have the option to change this.注意:我知道 Entity Framework 是首选,这是遗留应用程序,我无法更改它。 I tried binding the functions manually to the DataContext.Connection, no dice.我尝试将函数手动绑定到 DataContext.Connection,没有骰子。


Background regarding an attempt to modify System.Data.SQLite: I tried downloading the source code, I can successfully build from source, but the source code is a little puzzling to me.关于尝试修改 System.Data.SQLite 的背景:我尝试下载源代码,我可以成功地从源代码构建,但源代码让我有点困惑。

  • In the System.Data.SQLite.2012 project, there are no files included in the project, but all the source files exist in the actual folder.在 System.Data.SQLite.2012 项目中,项目中没有包含任何文件,但所有源文件都存在于实际文件夹中。 They appear to be included in the solution in a file called System.Data.SQLite.Files.targets.它们似乎包含在名为 System.Data.SQLite.Files.targets 的文件中的解决方案中。 This is a strange setup to me.这对我来说是一个奇怪的设置。
  • I added my custom functions to the project folder, but did not include them in the project just like all the other files.我将自定义函数添加到项目文件夹中,但没有像所有其他文件一样将它们包含在项目中。 I then added them to the System.Data.SQLite.Files.targets.然后我将它们添加到 System.Data.SQLite.Files.targets。
  • I built the solution and they do appear in the assembly.我构建了解决方案,它们确实出现在程序集中。 Although I can seem to add files to the assembly and build, modifying the existing code seems to have no affect.虽然我似乎可以将文件添加到程序集并构建,但修改现有代码似乎没有任何影响。
  • I went into the SQLiteConnection class and added a throw new Exception in the Open method, I've added Console.Writeline in key places, nothing I modify in the existing code seems to make it into the compiled assembly.我进入 SQLiteConnection 类并在 Open 方法中添加了一个 throw new Exception,我在关键位置添加了 Console.Writeline,我在现有代码中修改的任何内容似乎都没有进入编译程序集。

The goal of this was to try and build my custom functions into the System.Data.SQLite.dll rather than rely on auto loading through reflection.这样做的目的是尝试将我的自定义函数构建到 System.Data.SQLite.dll 中,而不是依赖于通过反射自动加载。

Just that moment I found this nice snippet 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]));
    }
}

But didn't find how to use it.但是没找到怎么用。 Now there's a SQLiteConnection.BindFunction method.现在有一个 SQLiteConnection.BindFunction 方法。 It's ugly so I made a little extension method:它很丑所以我做了一个小扩展方法:

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);
}

And now you just have to现在你只需要

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
}

Now how you can do it in LINQ to SQL, I don't exactly know because I've got my own SQL on LINQ IQueryProvider.现在你如何在 LINQ to SQL 中做到这一点,我不完全知道,因为我在 LINQ IQueryProvider 上有我自己的 SQL。 This is how you can do it with the basic IDbConnection, IDbCommand, IDbDataParameter and IDataReader interfaces and your custom SQLiteFunction.这就是您如何使用基本的 IDbConnection、IDbCommand、IDbDataParameter 和 IDataReader 接口以及您的自定义 SQLiteFunction 来完成此操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM