SQLite.net SQLiteFunction не работает в Linq to SQL

Я создал несколько специальных функций SQLite в С#, используя System.Data.SQLite.SQLiteFunction. Он отлично работает при использовании SQLiteDataAdapter для выполнения запросов, он не работает, однако при использовании Linq to SQL я получаю ошибки, заявляя, что функция не существует.

Я думаю, что в нижней строке есть , как я могу заставить пользовательские SQLiteFunctions работать в Linq to SQL? Либо, чтобы загрузить их так, как они должны, или, изменив исходный код SQLite.Net, чтобы они были частью dll?

Примечание. Я понимаю, что Entity Framework предпочтительнее, это устаревшее приложение, и у меня нет возможности изменить это. Я попытался связать функции вручную с DataContext.Connection, без кубиков.


Справочная информация о попытке изменить System.Data.SQLite: Я попытался загрузить исходный код, я могу успешно построить из исходного кода, но исходный код немного озадачивает меня.

  • В проекте System.Data.SQLite.2012 нет файлов, включенных в проект, но все исходные файлы существуют в фактической папке. Они, кажется, включены в решение в файл под названием System.Data.SQLite.Files.targets. Это странная установка для меня.
  • Я добавил свои пользовательские функции в папку проекта, но не включил их в проект так же, как и все другие файлы. Затем я добавил их в System.Data.SQLite.Files.targets.
  • Я построил решение, и они появляются в сборке. Хотя я могу добавить файлы в сборку и сборку, изменение существующего кода, похоже, не влияет.
  • Я зашел в класс SQLiteConnection и добавил новый метод Exception в методе Open, я добавил Console.Writeline в ключевых местах, ничего не меняя в существующем коде, похоже, попадает в сборку сборки.

Целью этого было попытаться создать мои пользовательские функции в System.Data.SQLite.dll, а не полагаться на автоматическую загрузку через отражение.

Ответ 1

Именно в этот момент я нашел этот хороший фрагмент из этого вопроса

// from /info/37454/createuse-user-defined-functions-in-systemdatasqlite
// 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, я точно не знаю, потому что у меня есть собственный SQL на LINQ IQueryProvider. Так вы можете сделать это с помощью базовых интерфейсов IDbConnection, IDbCommand, IDbDataParameter и IDataReader и вашей специальной SQLiteFunction.