2014-06-15 15 views
8

Ho creato una manciata di funzioni SQLite personalizzate in C# utilizzando System.Data.SQLite.SQLiteFunction. Funziona perfettamente quando si utilizza SQLiteDataAdapter per eseguire query, non funziona, tuttavia, quando si utilizza Linq su SQL, si verificano degli errori che indicano che la funzione non esiste.SQLite.net SQLiteFunction non funziona in Linq su SQL

Immagino che la linea di fondo sia, , come posso far funzionare le funzioni SQLite personalizzate in Linq su SQL? O caricandoli nel modo in cui dovrebbero o modificando il codice sorgente di SQLite.Net in modo che facciano parte della dll?

Nota: Comprendo che Entity Framework è preferibile, questa è un'applicazione legacy e non ho la possibilità di modificarlo. Ho provato a legare le funzioni manualmente a DataContext.Connection, senza dadi.


Sfondo per quanto riguarda un tentativo di modificare System.Data.SQLite: Ho provato a scaricare il codice sorgente, posso costruire con successo dai sorgenti, ma il codice sorgente è un po 'imbarazzante per me.

  • Nel progetto System.Data.SQLite.2012, non ci sono file inclusi nel progetto, ma tutti i file di origine sono presenti nella cartella corrente. Sembrano essere inclusi nella soluzione in un file chiamato System.Data.SQLite.Files.targets. Questa è una configurazione strana per me.
  • Ho aggiunto le mie funzioni personalizzate alla cartella del progetto, ma non le ho incluse nel progetto come tutti gli altri file. Poi li ho aggiunti a System.Data.SQLite.Files.targets.
  • Ho costruito la soluzione e vengono visualizzati nell'assieme. Sebbene possa sembrare che aggiunga file all'assemblaggio e alla build, la modifica del codice esistente sembra non avere alcun effetto.
  • Sono entrato nella classe SQLiteConnection e ho aggiunto una nuova eccezione di lancio nel metodo Open, ho aggiunto Console.Writeline in posizioni chiave, nulla di quello che ho modificato nel codice esistente sembra rientrare nell'assieme compilato.

L'obiettivo era cercare di creare le mie funzioni personalizzate nel System.Data.SQLite.dll piuttosto che fare affidamento sul caricamento automatico tramite reflection.

+1

È più difficile da leggere rispetto a "Twilight" – rpax

risposta

19

proprio in quel momento ho trovato questo bel frammento di 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])); 
    } 
} 

ma non ha trovato come usarlo. Ora c'è un metodo SQLiteConnection.BindFunction. E 'brutto così ho fatto un po' di metodo di estensione:

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

E ora devi solo

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 
} 

Ora come è possibile farlo in LINQ to SQL, io non so esattamente perché ho' Ho il mio SQL su LINQ IQueryProvider. Ecco come puoi farlo con le interfacce di base IDbConnection, IDbCommand, IDbDataParameter e IDataReader e la tua SQLiteFunction personalizzata.