Uso de SQLite.NET con Xamarin.iOS

La biblioteca de SQLite.NET que recomienda Xamarin es un ORM básico que permite almacenar y recuperar objetos en la base de datos local de SQLite en un dispositivo iOS. ORM significa Asignación relacional de objetos: una API que permite guardar y recuperar "objetos" de una base de datos sin escribir instrucciones SQL.

Uso

Para incluir la biblioteca de SQLite.NET en una aplicación de Xamarin, agregue el siguiente paquete NuGet al proyecto:

SQLite.NET NuGet package

Hay una serie de paquetes SQLite diferentes disponibles: asegúrese de elegir el correcto (es posible que no sea el resultado superior en la búsqueda).

Importante

SQLite.NET es una biblioteca de terceros compatible con el repositorio praeclarum/sqlite-net.

Una vez que tenga la biblioteca de SQLite.NET disponible, siga estos tres pasos para usarlo para acceder a una base de datos:

  1. Agregar una instrucción using: Agregue la siguiente instrucción a los archivos de C# donde se requiere acceso a los datos:

    using SQLite;
    
  2. Crear una base de datos en blanco: Se puede crear una referencia de base de datos pasando la ruta de acceso del archivo al constructor de clase SQLiteConnection. No es necesario comprobar si el archivo ya existe: se creará automáticamente si es necesario; de lo contrario, se abrirá el archivo de base de datos existente.

    var db = new SQLiteConnection (dbPath);
    

    La variable dbPath debe determinarse según las reglas descritas anteriormente en este documento.

  3. Guardar datos: Una vez creado un objeto SQLiteConnection, los comandos de base de datos se ejecutan llamando a sus métodos, como CreateTable e Insert como este:

    db.CreateTable<Stock> ();
    db.Insert (newStock); // after creating the newStock object
    
  4. Recuperar datos: Para recuperar un objeto (o una lista de objetos) use la sintaxis siguiente:

    var stock = db.Get<Stock>(5); // primary key id of 5
    var stockList = db.Table<Stock>();
    

Ejemplo de acceso a datos básicos

El código de ejemplo DataAccess_Basic de este documento tiene este aspecto cuando se ejecuta en iOS. El código muestra cómo realizar operaciones de SQLite.NET simples y muestra los resultados como texto en la ventana principal de la aplicación.

iOS

iOS SQLite.NET sample

En el ejemplo de código siguiente se muestra una interacción completa de la base de datos mediante la biblioteca de SQLite.NET para encapsular el acceso a la base de datos subyacente. Muestra lo siguiente:

  1. Creación del archivo de base de datos
  2. Insertar algunos datos mediante la creación de objetos y, a continuación, guardarlos
  3. Consultas de datos

Deberá incluir estos espacios de nombres:

using SQLite; // from the github SQLite.cs class

Esto requiere que haya agregado SQLite al proyecto, como se resalta aquí. Tenga en cuenta que la tabla de base de datos SQLite se define agregando atributos a una clase (la clase Stock ) en lugar de un comando CREATE TABLE.

[Table("Items")]
public class Stock {
    [PrimaryKey, AutoIncrement, Column("_id")]
    public int Id { get; set; }
    [MaxLength(8)]
    public string Symbol { get; set; }
}
public static void DoSomeDataAccess () {
       Console.WriteLine ("Creating database, if it doesn't already exist");
   string dbPath = Path.Combine (
        Environment.GetFolderPath (Environment.SpecialFolder.Personal),
        "ormdemo.db3");
   var db = new SQLiteConnection (dbPath);
   db.CreateTable<Stock> ();
   if (db.Table<Stock> ().Count() == 0) {
        // only insert the data if it doesn't already exist
        var newStock = new Stock ();
        newStock.Symbol = "AAPL";
        db.Insert (newStock);
        newStock = new Stock ();
        newStock.Symbol = "GOOG";
        db.Insert (newStock);
        newStock = new Stock ();
        newStock.Symbol = "MSFT";
        db.Insert (newStock);
    }
    Console.WriteLine("Reading data");
    var table = db.Table<Stock> ();
    foreach (var s in table) {
        Console.WriteLine (s.Id + " " + s.Symbol);
    }
}

El uso del atributo [Table] sin especificar un parámetro de nombre de tabla hará que la tabla de base de datos subyacente tenga el mismo nombre que la clase (en este caso, "Stock"). El nombre de tabla real es importante si escribe consultas SQL directamente en la base de datos en lugar de usar los métodos de acceso a datos ORM. Del mismo modo, el atributo [Column("_id")] es opcional y, si no hay una columna, se agregará a la tabla con el mismo nombre que la propiedad de la clase.

Atributos de SQLite

Los atributos comunes que puede aplicar a las clases para controlar cómo se almacenan en la base de datos subyacente incluyen:

  • [PrimaryKey]: Este atributo se puede aplicar a una propiedad entera para forzar que sea la clave principal de la tabla subyacente. No se admiten claves principales compuestas.
  • [AutoIncrement]: Este atributo hará que el valor de una propiedad entera se incremente automáticamente para cada nuevo objeto insertado en la base de datos.
  • [Column(name)]: El parámetro name establece el nombre de la columna de base de datos subyacente.
  • [Table(name)]: Marca la clase como capaz de almacenarse en una tabla de SQLite subyacente con el nombre especificado.
  • [MaxLength(value)]: Restringir la longitud de una propiedad de texto, cuando se intenta insertar una base de datos. El consumo de código debe validar esto antes de insertar el objeto, ya que este atributo solo se ‘comprueba’ cuando se intenta insertar o actualizar una base de datos.
  • [Omitir]: Hace que SQLite.NET omita esta propiedad. Esto resulta especialmente útil para las propiedades que tienen un tipo que no se puede almacenar en la base de datos o propiedades que no se pueden resolver automáticamente en SQLite.
  • [Único]: Garantiza que los valores de la columna de base de datos subyacente sean únicos.

La mayoría de estos atributos son opcionales. Siempre debe especificar una clave principal de entero para que las consultas de selección y eliminación se puedan realizar de forma eficaz en los datos.

Consultas más complejas

Los métodos siguientes en SQLiteConnection se pueden usar para realizar otras operaciones de datos:

  • Insertar: Agrega un nuevo objeto a la base de datos.
  • Obtener<T>: Intenta recuperar un objeto mediante la clave principal.
  • Tabla<T>: Devuelve todos los objetos de la tabla.
  • Eliminar: Elimina un objeto mediante su clave principal.
  • Consulta<T>: Realizar una consulta SQL que devuelve una serie de filas (como objetos).
  • Ejecutar: Use este método (y no Query) cuando no espere filas de nuevo desde SQL (como instrucciones INSERT, UPDATE y DELETE).

Obtención de un objeto mediante la clave principal

SQLite.Net proporciona el método Get para recuperar un único objeto en función de su clave principal.

var existingItem = db.Get<Stock>(3);

Selección de un objeto mediante Linq

Los métodos que devuelven colecciones admiten IEnumerable<T> para poder usar Linq para consultar o ordenar el contenido de una tabla. En el código siguiente se muestra un ejemplo con Linq para filtrar todas las entradas que comienzan por la letra “A”:

var apple = from s in db.Table<Stock>()
    where s.Symbol.StartsWith ("A")
    select s;
Console.WriteLine ("-> " + apple.FirstOrDefault ().Symbol);

Selección de un objeto mediante SQL

Aunque SQLite.Net puede proporcionar acceso basado en objetos a los datos, a veces es posible que tenga que realizar una consulta más compleja de la que permite Linq (o puede que necesite un rendimiento más rápido). Puede usar comandos SQL con el método Consulta, como se muestra aquí:

var stocksStartingWithA = db.Query<Stock>("SELECT * FROM Items WHERE Symbol = ?", "A");
foreach (var s in stocksStartingWithA) {
    Console.WriteLine ("a " + s.Symbol);
}

Importante

Al escribir instrucciones SQL directamente, se crea una dependencia de los nombres de las tablas y columnas de la base de datos, que se han generado a partir de las clases y sus atributos. Si cambia esos nombres en el código, debe recordar actualizar las instrucciones SQL escritas manualmente.

Eliminación de un objeto

La clave principal se usa para eliminar la fila, como se muestra aquí:

var rowcount = db.Delete<Stock>(someStock.Id); // Id is the primary key

Puede comprobar el rowcount para confirmar el número de filas afectadas (eliminadas en este caso).

Uso de SQLite.NET con varios subprocesos

SQLite admite tres modos de subproceso diferentes: Subproceso único, Multiproceso, y Serializado. Si desea acceder a la base de datos desde varios subprocesos sin restricciones, puede configurar SQLite para usar el modo de subproceso Serializado. Es importante establecer este modo al principio de la aplicación (por ejemplo, al principio del método OnCreate).

Para cambiar el modo de subproceso, llame aSqliteConnection.SetConfig que está en el espacio de nombres Mono.Data.Sqlite. Por ejemplo, esta línea de código configura SQLite para modo Serializado:

using Mono.Data.Sqlite;
...
SqliteConnection.SetConfig(SQLiteConfig.Serialized);