2010-11-23 15 views
27

Estoy usando SQLite con C# y tengo algunas tablas con claves foráneas definidas.Habilitación de restricciones de clave externa en SQLite

Ahora, sé que por defecto las restricciones de clave externa no se aplican en SQLite, pero me gustaría activarlas.

¿Es posible hacer esto a través del código? He buscado un relacionado question, pero no estoy seguro de cómo hacerlo a través del código C#. Estoy usando el último complemento de SQLite disponible para Visual Studio 2008 para diseñar mis tablas.

conn.Open(); 
SQLiteCommand cmd = new SQLiteCommand("PRAGMA foreign_keys = ON", conn); 
cmd.ExecuteNonQuery(); 
conn.Close(); 

Necesito este cambio para persistir cuando se vuelve a abrir esta conexión. ¿Es posible?

Respuesta

47

figurado Finalmente esto hacia fuera de this post. La configuración de PRAGMA foreign_key no persiste pero puede configurarla cada vez que se establezca la conexión en ConnectionString. Esto le permite usar los adaptadores de tabla de Visual Studio.

  1. Asegúrate de que tienes el latest version (1.0.73.0) de system.data.sqlite instalado (1.0.66.0 no funcionará).
  2. Cambie su ConnectionString a data source=C:\Dbs\myDb.db;foreign keys=true; (reemplace C: \ Dbs \ myDb.db con su base de datos sqlite).
+1

Estaba usando la versión 1.0.66.0. Seguí adelante sin la función de clave externa. Es bueno saber que este problema finalmente se resuelve. Lo tendré en cuenta para cualquier trabajo futuro. Gracias – kaustubh

+0

Intenté todos los demás métodos mencionados en esta publicación, y solo esta funcionó para mí. –

+0

Eres el hombre :) –

4

Encienda el pragma:

PRAGMA foreign_keys = ON; 

Usted puede ejecutar esta al igual que cualquier otra instrucción SQL.

+1

Estoy usando SqliteDataAdapter, gestiona la apertura y el cierre de las conexiones. Creo que cuando se cierra una conexión, esta información se pierde. ¿Cómo puedo hacer que esta información persista? – kaustubh

+0

@kaustubh: Tiene razón, el pragma foreign_key es sesión-local. No sé cómo funciona SqliteDataAdapter, pero parece tomar un parámetro SQLConnection en su constructor. ¿Podrías emitir el pragma contra la conexión cuando lo creas? –

+0

No parece haber una manera de especificar esta información en la cadena de conexión. ¿Hay alguna manera de especificar un comando que se ejecuta cada vez que se abre una conexión? – kaustubh

1

Parece que puede ejecutar el comando SQL PRAGMA foreign_keys = ON; en su conexión de base de datos al igual que lo haría con una instrucción Select o una actualización. Aunque debe asegurarse de que su SQLite se compiló con claves externas y cosas por el estilo. Ver Here.

2

Estos deben proporcionar la información que está buscando:

http://www.sqlite.org/faq.html#q22

http://www.sqlite.org/foreignkeys.html#fk_enable

En resumen, antes de versiones 3.6.19 no hacen cumplir las claves externas en absoluto, pero pueden ser simulado usando disparadores; comenzando con 3.6.19, se pueden aplicar claves foráneas, pero esto debe habilitarse por conexión usando la declaración PRAGMA foreign_keys = ON, y sqlite debe compilarse con activación de clave externa activada (lo que yo esperaría que fuera el caso de cualquier binario) distribución).

+0

Estoy usando SqliteDataAdapter que gestiona la apertura y el cierre de las conexiones de forma automática. ¿Cómo puedo, luego aplicar este PRAGMA cada vez que se realiza una actualización? – kaustubh

1

Agregar a la cadena de conexión: ";EnforceFKConstraints=Yes|True|1;"

+0

Estaba eufórico al ver su respuesta, parecía ser la solución perfecta ... Pero, por desgracia, no funciona :(Tal vez el proveedor de datos Sqlite para .NET aún no lo admite ... Si lo hace, entonces estoy en mi ingenio finaliza cómo hacer que funcione ... – kaustubh

+0

@kaustubh: intente utilizar [dbFacade] (http://krez0n.org.ua/wp-content/uploads/files/dbFacade.zip). ¿Tal vez esto lo respalde? [ El blog del autor] (http://krez0n.org.ua/archives/84) desafortunadamente está en ruso (él es de Ucrania, parece ser), pero puedo intentar ayudarte a traducir – abatishchev

+0

@kaustubh: por cierto, tienes agregó 'EnforceFKConstraints = Yes' o' EnforceFKConstraints = True' o 'EnforceFKConstraints = 1'. ¿O todos a la vez? – abatishchev

2

Otra solución es hacer "PRAGMA foreign_keys = ON" con cada consulta.

 
    SQLiteConnection connection = new SQLiteConnection("Data Source=" + dbSQLite + ";Read Only=False;"); 
    connection.Open(); 
    SQLiteCommand mycommand = new SQLiteCommand(connection); 
    mycommand.CommandText = "PRAGMA foreign_keys=ON"; 
    mycommand.ExecuteNonQuery(); 
    mycommand.CommandText = "DELETE FROM table WHERE ID=x"; 
    mycommand.ExecuteReader(); 
    connection.Close(); 

Si lo pone en una función a la que pasa el CommandText, puede reutilizarlo.

3

Yo también tuve problemas con este problema. Decidí investigar la cadena de conexión completa generada en SQLDriverConnect() al conectarme a la base de datos.Esto es lo que ha devuelto:

'Driver={SQLite3 ODBC Driver};Database=C:\Users\Staples\Documents\SQLLiteTest.s3db;StepAPI=;SyncPragma=;NoTXN=;Timeout=;ShortNames=;LongNames=;NoCreat=;NoWCHAR=;FKSupport=;JournalMode=;OEMCP=;LoadExt=;BigInt=;PWD=' 

Como se puede ver hay una propiedad FKSupport. Después de añadir FKSupport=True; a mi cadena de conexión se volvió esto:

'Driver={SQLite3 ODBCDriver};Database=C:\Users\Staples\Documents\SQLLiteTest.s3db;StepAPI=;SyncPragma=;NoTXN=;Timeout=;ShortNames=;LongNames=;NoCreat=;NoWCHAR=;FKSupport=True;JournalMode=;OEMCP=;LoadExt=;BigInt=;PWD=' 

y listo! las restricciones de claves extranjeras se aplican.

-1
In C++ store app the following code helped me to enable PRAGMA foreign_keys 
sqlite3_stmt* stmt; 
sqlite3_prepare(db, "PRAGMA foreign_keys = ON;", -1, &stmt, 0); 
sqlite3_step(stmt); 

I called this after creating db using the call of 

int rc = sqlite3_open16(path->Data(), &db); 
Cuestiones relacionadas