2010-09-30 17 views
12

Situación¿Cómo cambiar el diseño de la base de datos en una aplicación desplegada?

Estoy creando un C#/WPF 4 aplicación utilizando una base de datos SQL Compact Edition como backend con el marco de la entidad y despliegue con ClickOnce.

Soy bastante nuevo en aplicaciones que usan bases de datos, aunque no sospecho que tendré muchos problemas para diseñar y construir la base de datos original. Sin embargo, me preocupa que en el futuro necesite agregar o cambiar alguna funcionalidad que me obligue a cambiar el diseño de la base de datos después de que la base de datos ya esté implementada y el usuario tenga datos en la base de datos.

Preguntas

  1. ¿Es incluso posible empujar un diseño de base de datos actualizada a los usuarios a través de una actualización de ClickOnce de la misma manera lo es para los cambios de código?

  2. Si lo hiciera, ¿cómo se verían afectados los datos del usuario?

  3. ¿Cómo se hace este tipo de cosas en situaciones reales? ¿Cuáles son algunas de las mejores prácticas?

Calculo que en el peor de los casos, que había necesidad de construir algún tipo de número "versión" en la configuración de base de datos o del programa y crear una rutina para migrar la versión actual del usuario de la base de datos a la nueva uno.

Agradezco cualquier idea sobre mi problema. Muchas gracias.

+3

vewy, vewy, carefwy – annakata

Respuesta

12

Existen algunos "trucos" que se utilizan al diseñar bases de datos para permitir cambios de diseño.

En primer lugar, muchos diseñadores de bases de datos crean vistas para codificar en lugar de codificarlas directamente en las tablas. Esto permite que las tablas se modifiquen (se dividan o combinen, etc.) y solo se requiere que las vistas se actualicen. Es posible que desee investigar técnicas database refactoring para esto.

En segundo lugar, puede agregar información de control de versiones a la base de datos (comúnmente hecha como una tabla de 'versión' con un solo campo). La actualización de la base de datos se puede hacer a través de código o mediante scripts. Un sistema en el que trabajé verificaba automáticamente la versión de la base de datos y luego actualizaba progresivamente el esquema a través de versiones en código hasta que coincidía con la versión requerida para el tiempo de ejecución. Esto fue toda una empresa.

+1

+1 Trabajo en un sistema que comprueba las versiones de la base de datos y actualiza el esquema mediante código (combinación de sentencias de definición de datos SQL y código para manipular la estructura de la base de datos, a través de ADO en nuestro caso).La única alternativa que puedo pensar es extraer los datos del usuario de las viejas bases de datos en una nueva y limpia base de datos. Eso también sería una empresa bastante grande. – MarkJ

+0

+1 para ver abstracciones – annakata

+0

Gracias por la respuesta. SQL Server CE no admite vistas, pero ese truco puede ser útil para otros. =) Creo que voy a implementar algún sistema para migrar recursivamente datos de usuario versión por versión a la versión actual de la base de datos. Eso también me facilitará lidiar con la situación de restaurar copias de seguridad que podrían ser de versiones anteriores. (Sin embargo, creo que haré todo lo posible para diseñar la base de datos, por lo que _need_ actualizar mucho!) –

2

Creo que su "peor" caso es en realidad una ruta bastante buena para ir en esta situación. Mantenga una versión de base de datos en el DB y haga que su aplicación verifique y actualice el DB según sea necesario. Si construye su actualizador correctamente, debería poder mantener los datos del usuario. Dependiendo de la actualización, esto podría implicar la creación de tablas temporales para contener los datos existentes y repoblar nuevas versiones de las tablas a partir de ellos. Es posible que pueda include a new SDF file con el nuevo esquema en el lugar en el proceso de actualización y simplemente transferir los datos. Podría ser un poco más fácil de esa manera: podría usar nombres de archivos para diferenciar versiones y activar el código de actualización de esa manera.

+0

Sí, si voy con el 'peor caso' crearía una nueva SDF vacía y transferiría los datos del usuario de lo viejo a lo nuevo, cambia el nombre del archivo o algo similar a eso. –

2

Desafortunadamente, el control de versiones y la administración de cambios para bases de datos es desesperadamente desesperadamente lejos de lo que puede hacer con el resto de su código.

Si tiene un entorno interno solo hay una serie de herramientas que lo ayudarán (DBGhost, Red Gate tiene una aplicación nueva, algunas aplicaciones de administración de implementación) pero todas ellas son menos que soluciones completas, pero son en su mayoría lo suficientemente buenos.

Para las soluciones enviadas por el cliente, realmente no tengo nada mejor que su peor caso, me temo. Solo trate de diseñar con flexibilidad en mente - vea la respuesta de Dr.Herbie.

Esto básicamente no es un problema resuelto.

2

"Despliegue de cliente inteligente con ClickOnce" por Brian Noyes tiene un excelente capítulo sobre este tema. (Capítulo 5) ISBN 978-0-32-119769-6

Sugiere algo como esto:

if(ApplicationDeployment.CurrentDeployment.IsFirstRun) { 
    MigrateData(); 
} 

private void MigrateData() { 
    string previousDb = Path.Combine(ApplicationDeployment.CurrentDeployment.DataDirectory, @".\pre\mydb.sdf"); 

    if(!File.Exists(previousDb)) 
     return; 

    string oldConnString = @"Data Source=|DataDirectory|\.pre\mydb.sdf"; 
    string newConnString = @"Data Source=|DataDirectory|\mydb.sdf"; 

    //If you are using datasets perform any migration here, with the old and new table adapters. 
    //Otherwise use an .sql data migration script. 
    //Store the version of the database in the database, and check that in the beginning of your update script and GOTO the correct line in the SQL script. 

} 
+0

Eso suena como un libro útil. Definitivamente lo verificaré. Gracias. –

+0

Tengo ese libro. Tiene una sección sobre mi situación casi exactamente. Muchas gracias por la sugerencia del libro, realmente me enseñó mucho sobre ClickOnce. –

+0

@Benny Jobigan, qué hay de eso - copie el archivo de ".pre" a predeterminado (es decir, a DataDirectory) y ejecute solo las secuencias de comandos de actualización, por ejemplo. ALTER TABLE ... ADD COLUMN ... ¿Qué piensas al respecto? – prostynick

2

Una solución común es incluir un número de versión en alguna parte de la base de datos. Si tiene una tabla con datos misceláneos del sistema, ejecútelo allí o cree una tabla con un registro solo para contener el número de versión de DB. Luego, cada vez que se inicia el programa, verifique si la versión de la base de datos es menor que la versión esperada. Si es así, ejecute los comandos SQL CREATE, ALTER, etc. requeridos para actualizarlo. Tener un script o función para cada cambio de versión. Entonces, si ve que la base de datos se encuentra actualmente en la versión 6 y el código espera la versión 8, ejecute la actualización 6 a 7 y la actualización 7 a 8.

Otro método que usamos en un proyecto que trabajé fue enviar una base de datos de datos con el código. Cada vez que instaló una nueva versión, el instalador también instalaría la última copia de esta nueva base de datos en blanco. Luego, cuando el programa lo puso en marcha, compararía el esquema de la base de datos actual del usuario con el nuevo esquema de la base de datos y determinaría qué cambios de la base de datos se necesitaban sobre la marcha. Al igual que si en la tabla "esquema de referencia" Foo tuviera una columna llamada Bar, y no hubiera una barra de columna en la base de datos actual del usuario, generaríamos una "tabla alter Foo agregar barra ..." y la ejecutaremos. Mientras escribía el primer borrador del programa para hacer esto fue una buena cantidad de trabajo, una vez que lo habíamos hecho, prácticamente no había mantenimiento para mantener el esquema de DB actualizado. La conversión se acaba de hacer sobre la marcha.

Tenga en cuenta que este esquema no maneja los cambios de base de datos que requieren cambios de valores de datos, como si agrega una nueva columna que debe rellenarse inicialmente haciendo algún cálculo en datos de otras tablas o algo así. Pero si puede generar nuevos datos a partir de datos antiguos, eso debe significar que los nuevos datos son redundantes y su base de datos no está normalizada. No creo que la situación alguna vez nos haya sucedido.

0

Tuve el mismo problema con una aplicación en Android con una base de datos SQLite que agrega una tabla. Cambié el nombre de la base de datos para incluir una extensión de versión, como: theDataBaseV1, eliminé la anterior y la aplicación funciona bien.

acabo de cambiar el nombre de la base de datos y el nombre de esta línea de código

private static final String DATABASE_NAME = "busesBogotaV2.db"; 

en el DBManager cuando su va a abrir.

¿Alguien sabe si esta solución trivial tiene alguna consecuencia no deseada?

+0

En Android, si está utilizando [SQLiteOpenHelper] (http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html), tiene un método que puede anular para ayudarlo a migrar el archivo db en la actualización y degradación. –

+0

sí, lo sé, pero en mi caso no tengo ninguna versión en la base de datos. Tengo 10'000 descargas con un simple simple db, ¿cómo puedo incorporar la versión? si ya hay una aplicación desplegada? –

Cuestiones relacionadas