Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. 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.

I guess the bottom line is, how can I get the Custom SQLiteFunctions to work in 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?

Note: I understand Entity Framework is preferred, this is legacy application and I do not have the option to change this. I tried binding the functions manually to the DataContext.Connection, no dice.


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.

  • 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. They appear to be included in the solution in a file called 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.
  • 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.

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.

like image 649
Matthew McClaskey Avatar asked Jun 15 '14 12:06

Matthew McClaskey


People also ask

Can I use LINQ with SQLite?

LinqConnect (formerly known as LINQ to SQLite) is a fast and lightweight ORM solution, which is closely compatible to Microsoft LINQ to SQL and contains its own advanced features, such as complex type support, advanced data fetching options, configurable compiled query caching, and others.

Which is better Entity Framework or LINQ to SQL?

LINQ to SQL allow you to query and modify SQL Server database by using LINQ syntax. Entity framework is a great ORM shipped by Microsoft which allow you to query and modify RDBMS like SQL Server, Oracle, DB2 and MySQL etc. by using LINQ syntax. Today, EF is widely used by each and every .

How does LINQ to SQL work?

When the application runs, LINQ to SQL translates into SQL the language-integrated queries in the object model and sends them to the database for execution. When the database returns the results, LINQ to SQL translates them back to objects that you can work with in your own programming language.

Can we use LINQ without Entity Framework?

No. Linq as in query over the data-in-memory that was loaded using your stored procedures (which means that your queries won't be translated to SQL)?


1 Answers

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. 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. This is how you can do it with the basic IDbConnection, IDbCommand, IDbDataParameter and IDataReader interfaces and your custom SQLiteFunction.

like image 169
metadings Avatar answered Nov 09 '22 00:11

metadings