Database

Persistencia en Android


Los tipos de persistencia en Android, por lo general, puede dividirse en tres grupos:

  • Preferencias compartidas: conjunto de pares clave-valor. Pueden ser privadas (únicamente accesibles desde la aplicación) o compartidas con otras aplicaciones.
  • Ficheros: una aplicación Android puede almacenar y consultar datos tanto de la carpeta privada de la aplicación como de la tarjeta SD.
  • Base de datos: cada aplicación puede disponer de una base de datos local en formato SQLite en la que realizar operaciones SQL como si de un SGDB normal y corriente se tratara.

A continuación pasaremos a explicar en qué consisten y cómo utilizar estos tres tipos de persistencia.

Estructura interna de la aplicación

Cada aplicación que se instala en el dispositivo crea una carpeta con el nombre de su paquete principal dentro de la ruta /data/data de la memoria interna del dispositivo. Dentro de esa carpeta privada (que no puede ser accedida por ningún otro proceso salvo que se disponga de un terminal de desarrollo o se “rootee” el dispositivo) se aloja una estructura en la que, entre otros, se encuentran las siguientes carpetas:

  • /shared_prefs: contiene un conjunto de ficheros XML que se corresponden a los nombres de las preferencias compartidas. Almacena un mapa con pares clave-valor.
  • /files: contiene los archivos del sistema, que pueden ser binarios o de texto.
  • /databases: contiene las bases de datos SQLite asociadas a la aplicación.
  • /cache: contiene los datos temporales de la aplicación

Directorio interno de la aplicación

A continuación veremos con un poco más de detalle el significado de estos directorios y la relación con los medios de persistencia que Android ofrece.

(más…)

Obteniendo el esquema de una Tabla de SQL Server


Hay lugares en los que la generación automática de código no está del todo bien vista. Sin embargo, utilizando las herramientas apropiadas, un generador de código simple puede ahorrar muchas horas de trabajo.
Esta introducción parece no tener demasiado que ver con el título del artículo, pero en realidad está bastante relacionada.

La razón es la siguiente: hemos visto previamente, cuando hablábamos del patrón DAO, que la necesidad de crear entidades DTO para cada tabla de la base de datos era una realidad.

Bien, hasta aquí todo claro. Pero… ¿y si fuese posible crear estos ficheros de forma automática? ¿Cómo? Preguntándole a la base de datos qué tablas y campos posee, y generando a partir de ellos el código necesario para implementar un DTO. Y todo ello sin despeinarnos.
Este artículo trata de hacer un breve inciso en el principio en el que se basa dicha generación de código. Únicamente veremos el mecanismo por el cual preguntar a la base de datos por estos parámetros. Hecho esto, podremos crear un fichero fuente con facilidad.

Para comenzar, declararemos un método que, a partir de una conexión de tipo Sql Server, devuelva un DataSet con una colección de tablas, cuyo nombre sea el propio nombre de la tabla y sus campos sean los datos de dichas tablas que queramos obtener.


      public DataSet ObtenerEsquemaBD(SqlConnection Conexion)
        {

Lo primero que haremos será abrir la conexión, con su correspondiente comprobación de nulos (es decir, si la conexión existe o no).

            try
            {
                if (!(Conexion == null))
                {
                    // Abrimos la conexión
                    if (!(Conexion.State == ConnectionState.Open))
                    {
                        Conexion.Open();
                    }

Seguidamente, crearemos un DataTable para almacenar los nombres de las tablas de la base de datos, así como un DataSet y un DataAdapter para almacenar los datos de las consultas. Utilizaremos una cadena de texto para almacenar las sentencias de las consultas.

                    // Creamos un DataTable para almacenar los nombres de las tablas de la base de datos
                    DataTable dtTablas = new DataTable();

                    // Creamos un DataSet y un DataAdapter para obtener los datos
                    DataSet ds = new DataSet();
                    SqlDataAdapter da = new SqlDataAdapter();

                    // Declaramos una cadena para la consulta
                    string sSQL;

Indicaremos que queremos obtener las tablas de la Base de Datos, y lo almacenamos en el DataTable destinado a ello mediante el DataAdapter

                    sSQL = "SELECT TABLE_NAME as Tabla FROM Information_Schema.Tables";
                    da.SelectCommand = new SqlCommand(sSQL, Conexion);
                    da.Fill(dtTablas);

Ahora recorreremos la tabla que contiene los nombres de cada tabla, realizando una consulta por cada una de ellas. En esta consulta obtendremos datos como el nombre de columna, si admite nulos o no, el tipo de dato…

                    foreach (DataRow dr in dtTablas.Rows)
                    {
                        if(!dr.IsNull("Tabla"))
                        {
                            DataTable dt = new DataTable();
                            sSQL = ("SELECT TABLE_CATALOG as Db, TABLE_NAME as Tabla, ORDINAL_POSITION as Posicion, COLUMN_NAME as Columna" +
                            ", IS_NULLABLE as AdmiteNulos, DATA_TYPE as TipoDatos, CHARACTER_MAXIMUM_LENGTH as MaxChar FROM Infor" +
                            "mation_Schema.Columns WHERE TABLE_NAME = \'"
                                        + (dr["Tabla"].ToString() + "\'"));
                            da.SelectCommand = new SqlCommand(sSQL, Conexion);
                            da.Fill(dt);

                            // Hecha la consulta, añadimos la tabla obtenida por este procedimiento a nuestro DataSet
                            dt.TableName = dr["Tabla"].ToString();
                            ds.Tables.Add(dt);
                        }
                    }

Finalmente, cerramos la conexión y devolvemos el DataSet

                    Conexion.Close();
                    return ds;
                }
                else
                {
                    Conexion.Close();
                    return null;
                }
            }
            catch (Exception ex)
            {
                throw(ex);
            }
        }

El resultado aparecerá en el DataSet, almacenando, por lo tanto, un esquema por cada tabla.

090501Tablas