private static void InyectarSqlDesdeRecurso(Lfx.Data.Connection dataBase, string archivo) { dataBase.RequiresTransaction = false; System.IO.Stream RecursoActualizacion = Lfx.Workspace.ObtenerRecurso(archivo); if (RecursoActualizacion != null) { System.IO.StreamReader Lector = new System.IO.StreamReader(RecursoActualizacion); string SqlActualizacion = dataBase.CustomizeSql(Lector.ReadToEnd()); RecursoActualizacion.Close(); try { dataBase.ExecuteSql(SqlActualizacion); } catch { // Falló la ejecución... intento los comandos SQL de a uno, ignorando el que de un error do { string Comando = Data.Connection.GetNextCommand(ref SqlActualizacion); try { dataBase.ExecuteSql(Comando); } catch { if (Lfx.Environment.SystemInformation.DesignMode) { throw; } } }while (SqlActualizacion.Length > 0); } } }
/// <summary> /// Verifica la estructura de la base de datos actual y si es necesario modifica para que esté conforme /// al diseño de referencia. /// </summary> /// <param name="dataBase">PrintDataBase mediante el cual se accede a la base de datos.</param> /// <param name="omitPreAndPostSql">Omitir la ejecución de comandos Pre- y Post-actualización de estructura. Esto es útil cuando se actualiza una estructura vacía, por ejemplo al crear una base de datos nueva.</param> /// /// <param name="progreso">El objeto sobre el cual reportar el progreso.</param> public void CheckAndUpdateDataBaseStructure(Lfx.Data.Connection dataBase, bool omitPreAndPostSql, Lfx.Types.OperationProgress progreso) { progreso.ChangeStatus("Verificando estructuras de datos"); bool MustEnableConstraints = false; if (dataBase.ConstraintsEnabled) { dataBase.EnableConstraints(false); MustEnableConstraints = true; } if (omitPreAndPostSql == false) { progreso.ChangeStatus("Ejecutando guión previo..."); InyectarSqlDesdeRecurso(dataBase, @"Data.Struct.db_upd_pre.sql"); } //Primero borro claves foráneas (deleteOnly = true) progreso.ChangeStatus("Eliminando reglas obsoletas..."); dataBase.SetConstraints(Lfx.Workspace.Master.Structure.Constraints, true); try { dataBase.ExecuteSql("FLUSH TABLES"); } catch { // No tengo permiso... no importa } progreso.Max = Lfx.Workspace.Master.Structure.Tables.Count; foreach (Lfx.Data.TableStructure Tab in Lfx.Workspace.Master.Structure.Tables.Values) { string TableLabel = Tab.Label; if (Tab.Label == null) { TableLabel = Tab.Name.ToTitleCase(); } progreso.ChangeStatus(progreso.Value + 1, "Verificando " + TableLabel); dataBase.SetTableStructure(Tab); } //Ahora creo claves nuevas (deleteOnly = false) progreso.ChangeStatus("Estableciendo reglas de integridad"); try { dataBase.ExecuteSql("FLUSH TABLES"); } catch { // No tengo permiso... no importa } dataBase.SetConstraints(Lfx.Workspace.Master.Structure.Constraints, false); if (omitPreAndPostSql == false) { progreso.ChangeStatus("Ejecutando guión posterior..."); InyectarSqlDesdeRecurso(dataBase, @"Data.Struct.db_upd_post.sql"); } if (MustEnableConstraints) { dataBase.EnableConstraints(true); } }
private void FormPrincipal_KeyDown(object sender, KeyEventArgs e) { switch (e.KeyCode) { case Keys.F10: case Keys.F12: if (e.Shift == false && e.Alt == false && e.Shift == false) { e.Handled = true; if (FormInicio == null) { MostrarAyuda("Menú principal", "Utilice las teclas de cursor (flechas) para navegar el menú. Pulse <Intro> (o <Enter>) para ejecutar una opción."); System.Windows.Forms.SendKeys.Send("%S"); } else { MostrarAyuda("Pantalla de inicio", "Si no encuentra lo que busca en la pantalla de inicio utilice el menú en la parte superior."); FormInicio.Focus(); } } break; case Keys.I: if (e.Control == true && e.Alt == true && Lbl.Sys.Config.Actual.UsuarioConectado.TieneAccesoGlobal()) { e.Handled = true; System.Windows.Forms.OpenFileDialog DialogoArchivo = new System.Windows.Forms.OpenFileDialog(); DialogoArchivo.DefaultExt = "sql"; DialogoArchivo.Filter = "Archivo SQL|*.sql"; DialogoArchivo.Multiselect = false; DialogoArchivo.Title = "Inyectar SQL"; if (DialogoArchivo.ShowDialog() == System.Windows.Forms.DialogResult.OK) { using (System.IO.Stream Archivo = System.IO.File.OpenRead(DialogoArchivo.FileName)) using (System.IO.StreamReader Lector = new System.IO.StreamReader(Archivo, System.Text.Encoding.Default)) using (Lfx.Data.Connection ConexionActualizar = Lfx.Workspace.Master.GetNewConnection("Inyectar SQL")) using (IDbTransaction Trans = ConexionActualizar.BeginTransaction()) { string SqlActualizacion = ConexionActualizar.CustomizeSql(Lector.ReadToEnd()); do { string Comando = Lfx.Data.Connection.GetNextCommand(ref SqlActualizacion); try { ConexionActualizar.ExecuteSql(Comando); } catch (Exception ex) { Lfx.Workspace.Master.RunTime.Toast(Comando + System.Environment.NewLine + System.Environment.NewLine + ex.Message, "Error al inyectar datos"); } }while (SqlActualizacion.Length > 0); Trans.Commit(); } } } break; case Keys.B: if (e.Control && e.Alt == false && e.Shift == false) { e.Handled = true; BarraInferior.Visible = !BarraInferior.Visible; Lfx.Workspace.Master.CurrentConfig.WriteLocalSetting("Sistema", "Apariencia.BarraInformacion", BarraInferior.Visible ? 1 : 0); } break; case Keys.J: if (e.Control == true && e.Alt == false && e.Shift == false) { e.Handled = true; string Cmd = Lui.Forms.InputBox.ShowInputBox("Comando"); if (Cmd != null && Cmd.Length > 0) { Ejecutor.Exec(Cmd); } } break; case Keys.F: if (e.Control == true && e.Alt == false && e.Shift == false) { e.Handled = true; Ejecutor.Exec("CREAR Lbl.Comprobantes.Factura"); } break; case Keys.T: if (e.Control == true && e.Alt == false && e.Shift == false) { e.Handled = true; Ejecutor.Exec("CREAR Lbl.Comprobantes.Ticket"); } break; case Keys.P: if (e.Control == true && e.Alt == false && e.Shift == false) { e.Handled = true; Ejecutor.Exec("CREAR Lbl.Comprobantes.Presupuesto"); } break; case Keys.R: if (e.Control == true && e.Alt == false && e.Shift == false) { e.Handled = true; Ejecutor.Exec("CREAR Lbl.Comprobantes.ReciboDeCobro"); } break; case Keys.L: if (e.Control == true && e.Alt == false && e.Shift == false) { e.Handled = true; Ejecutor.Exec("CALC"); } break; } }
public void Restore(string backupName) { string Carpeta = backupName + System.IO.Path.DirectorySeparatorChar; Lfx.Environment.Folders.EnsurePathExists(this.BackupPath); if (Carpeta != null && Carpeta.Length > 0 && System.IO.Directory.Exists(this.BackupPath + Carpeta)) { bool UsandoArchivoComprimido = false; Lfx.Types.OperationProgress Progreso = new Lfx.Types.OperationProgress("Restaurando copia de seguridad", "Este proceso va a demorar varios minutos. Por favor no lo interrumpa"); Progreso.Modal = true; /* Progreso.ChangeStatus("Descomprimiendo"); * // Descomprimir backup si está comprimido * if (System.IO.File.Exists(BackupPath + Carpeta + "backup.7z")) { * Lfx.FileFormats.Compression.Archive ArchivoComprimido = new Lfx.FileFormats.Compression.Archive(BackupPath + Carpeta + "backup.7z"); * ArchivoComprimido.ExtractAll(BackupPath + Carpeta); * UsandoArchivoComprimido = true; * } */ Progreso.ChangeStatus("Eliminando datos actuales"); using (Lfx.Data.Connection DataBase = Lfx.Workspace.Master.GetNewConnection("Restauración de copia de seguridad")) { Progreso.ChangeStatus("Acomodando estructuras"); Lfx.Workspace.Master.Structure.TagList.Clear(); Lfx.Workspace.Master.Structure.LoadFromFile(this.BackupPath + Carpeta + "dbstruct.xml"); Lfx.Workspace.Master.CheckAndUpdateDataBaseVersion(true, true); using (BackupReader Lector = new BackupReader(this.BackupPath + Carpeta + "dbdata.lbd")) using (IDbTransaction Trans = DataBase.BeginTransaction()) { DataBase.EnableConstraints(false); Progreso.ChangeStatus("Incorporando tablas de datos"); Progreso.Max = (int)(Lector.Length / 1024); string TablaActual = null; string[] ListaCampos = null; object[] ValoresCampos = null; int CampoActual = 0; bool EndTable = false; qGen.BuilkInsert Insertador = new qGen.BuilkInsert(); do { string Comando = Lector.ReadString(4); switch (Comando) { case ":TBL": TablaActual = Lector.ReadPrefixedString4(); string NombreTabla; if (Lfx.Workspace.Master.Structure.Tables.ContainsKey(TablaActual) && Lfx.Workspace.Master.Structure.Tables[TablaActual].Label != null) { NombreTabla = Lfx.Workspace.Master.Structure.Tables[TablaActual].Label; } else { NombreTabla = TablaActual.ToTitleCase(); } EndTable = false; Progreso.ChangeStatus("Cargando " + NombreTabla); qGen.Delete DelCmd = new qGen.Delete(TablaActual); DelCmd.EnableDeleleteWithoutWhere = true; DataBase.Execute(DelCmd); break; case ":FDL": ListaCampos = Lector.ReadPrefixedString4().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); ValoresCampos = new object[ListaCampos.Length]; CampoActual = 0; break; case ":FLD": ValoresCampos[CampoActual++] = Lector.ReadField(); break; case ".ROW": qGen.Insert Insertar = new qGen.Insert(TablaActual); for (int i = 0; i < ListaCampos.Length; i++) { Insertar.Fields.AddWithValue(ListaCampos[i], ValoresCampos[i]); } Insertador.Add(Insertar); ValoresCampos = new object[ListaCampos.Length]; CampoActual = 0; break; case ":REM": Lector.ReadPrefixedString4(); break; case ".TBL": EndTable = true; break; } if (EndTable || Insertador.Count >= 1000) { if (Insertador.Count > 0) { DataBase.Execute(Insertador); } Insertador.Clear(); Progreso.Value = (int)(Lector.Position / 1024); } } while (Lector.Position < Lector.Length); Lector.Close(); if (Lfx.Workspace.Master.MasterConnection.SqlMode == qGen.SqlModes.PostgreSql) { // PostgreSql: Tengo que actualizar las secuencias Progreso.ChangeStatus("Actualizando secuencias"); string PatronSecuencia = @"nextval\(\'(.+)\'(.*)\)"; foreach (string Tabla in Lfx.Data.DataBaseCache.DefaultCache.GetTableNames()) { string OID = DataBase.FieldString("SELECT c.oid FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid=c.relnamespace WHERE pg_catalog.pg_table_is_visible(c.oid) AND c.relname ~ '^" + Tabla + "$'"); System.Data.DataTable Campos = DataBase.Select("SELECT a.attname,pg_catalog.format_type(a.atttypid, a.atttypmod),(SELECT substring(d.adsrc for 128) FROM pg_catalog.pg_attrdef d WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef), a.attnotnull, a.attnum FROM pg_catalog.pg_attribute a WHERE a.attrelid = '" + OID + "' AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum"); foreach (System.Data.DataRow Campo in Campos.Rows) { if (Campo[2] != DBNull.Value && Campo[2] != null) { string DefaultCampo = System.Convert.ToString(Campo[2]); if (Regex.IsMatch(DefaultCampo, PatronSecuencia)) { string NombreCampo = System.Convert.ToString(Campo[0]); foreach (System.Text.RegularExpressions.Match Ocurrencia in Regex.Matches(DefaultCampo, PatronSecuencia)) { string Secuencia = Ocurrencia.Groups[1].ToString(); int MaxId = DataBase.FieldInt("SELECT MAX(" + NombreCampo + ") FROM " + Tabla) + 1; DataBase.ExecuteSql("ALTER SEQUENCE " + Secuencia + " RESTART WITH " + MaxId.ToString()); } } } } } } if (System.IO.File.Exists(this.BackupPath + Carpeta + "blobs.lst")) { // Incorporar Blobs Progreso.ChangeStatus("Incorporando imágenes"); System.IO.StreamReader LectorBlobs = new System.IO.StreamReader(this.BackupPath + Carpeta + "blobs.lst", System.Text.Encoding.Default); string InfoImagen = null; do { InfoImagen = LectorBlobs.ReadLine(); if (InfoImagen != null && InfoImagen.Length > 0) { string Tabla = Lfx.Types.Strings.GetNextToken(ref InfoImagen, ","); string Campo = Lfx.Types.Strings.GetNextToken(ref InfoImagen, ","); string CampoId = Lfx.Types.Strings.GetNextToken(ref InfoImagen, ","); string NombreArchivoImagen = Lfx.Types.Strings.GetNextToken(ref InfoImagen, ","); // Guardar blob nuevo qGen.Update ActualizarBlob = new qGen.Update(DataBase, Tabla); ActualizarBlob.WhereClause = new qGen.Where(Campo, CampoId); System.IO.FileStream ArchivoImagen = new System.IO.FileStream(this.BackupPath + Carpeta + NombreArchivoImagen, System.IO.FileMode.Open, System.IO.FileAccess.Read); byte[] Contenido = new byte[System.Convert.ToInt32(ArchivoImagen.Length) - 1 + 1]; ArchivoImagen.Read(Contenido, 0, System.Convert.ToInt32(ArchivoImagen.Length)); ArchivoImagen.Close(); ActualizarBlob.Fields.AddWithValue(Campo, Contenido); DataBase.Execute(ActualizarBlob); } }while (InfoImagen != null); LectorBlobs.Close(); } if (UsandoArchivoComprimido) { Progreso.ChangeStatus("Eliminando archivos temporales"); // Borrar los archivos que descomprim temporalmente System.IO.DirectoryInfo Dir = new System.IO.DirectoryInfo(this.BackupPath + Carpeta); foreach (System.IO.FileInfo DirItem in Dir.GetFiles()) { if (DirItem.Name != "backup.7z" && DirItem.Name != "info.txt") { System.IO.File.Delete(this.BackupPath + Carpeta + DirItem.Name); } } } Progreso.ChangeStatus("Terminando transacción"); Trans.Commit(); } Progreso.End(); } Lfx.Workspace.Master.RunTime.Toast("La copia de seguridad se restauró con éxito. A continuación se va a reiniciar la aplicación.", "Copia Restaurada"); } }
/// <summary> /// Verifica la versión de la base de datos y si es necesario actualiza. /// </summary> /// <param name="ignorarFecha">Ignorar la fecha y actualizar siempre.</param> /// <param name="noTocarDatos">Actualizar sólo la estructura. No incorpora ni modifica datos.</param> public void CheckAndUpdateDataBaseVersion(bool ignorarFecha, bool noTocarDatos) { using (Lfx.Data.Connection Conn = Lfx.Workspace.Master.GetNewConnection("Verificar estructura de la base de datos")) { Conn.RequiresTransaction = false; int VersionActual = this.CurrentConfig.ReadGlobalSetting <int>("Sistema.DB.Version", 0); if (VersionUltima < VersionActual) { this.RunTime.Toast("Es necesario actualizar Lázaro en esta estación de trabajo. Se esperaba la versión " + VersionUltima.ToString() + " de la base de datos, pero se encontró la versión " + VersionActual.ToString() + " que es demasiado nueva.", "Aviso"); return; } // Me fijo si ya hay alguien verificando la estructura string FechaInicioVerif = Lfx.Workspace.Master.CurrentConfig.ReadGlobalSetting <string>("Sistema.VerificarVersionBd.Inicio", string.Empty); string FechaInicioVerifMax = Lfx.Types.Formatting.FormatDateTimeSql(System.DateTime.Now.AddMinutes(10).ToUniversalTime()); if (ignorarFecha == false && string.Compare(FechaInicioVerif, FechaInicioVerifMax) > 0) { // Ya hay alguien verificando return; } DateTime VersionEstructura = Lfx.Types.Parsing.ParseSqlDateTime(this.CurrentConfig.ReadGlobalSetting <string>("Sistema.DB.VersionEstructura", "2000-01-01 00:00:00")); DateTime FechaLazaroExe = new System.IO.FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).LastWriteTime; TimeSpan Diferencia = FechaLazaroExe - VersionEstructura; System.Console.WriteLine("Versión estructura: " + VersionEstructura.ToString()); System.Console.WriteLine("Versión Lázaro : " + FechaLazaroExe.ToString() + " (" + Diferencia.ToString() + " más nuevo)"); if ((noTocarDatos || VersionActual == VersionUltima) && (ignorarFecha == false && Diferencia.TotalHours <= 1)) { // No es necesario actualizar nada return; } Lfx.Types.OperationProgress Progreso = new Types.OperationProgress("Verificando estructuras de datos", "Se está analizando la estructura del almacén de datos y se van a realizar cambios si fuera necesario"); Progreso.Modal = true; Progreso.Begin(); Lfx.Workspace.Master.CurrentConfig.WriteGlobalSetting("Sistema.VerificarVersionBd.Inicio", Lfx.Types.Formatting.FormatDateTimeSql(Lfx.Workspace.Master.MasterConnection.ServerDateTime.ToUniversalTime())); Lfx.Workspace.Master.CurrentConfig.WriteGlobalSetting("Sistema.VerificarVersionBd.Estacion", Lfx.Environment.SystemInformation.MachineName); try { Conn.ExecuteSql("FLUSH TABLES"); } catch { // No tengo permiso... no importa } if (noTocarDatos == false && VersionActual < VersionUltima && VersionActual > 0) { //Actualizo desde la versión actual a la última for (int i = VersionActual + 1; i <= VersionUltima; i++) { Progreso.ChangeStatus("Pre-actualización " + i.ToString()); InyectarSqlDesdeRecurso(Conn, @"Data.Struct.db_upd" + i.ToString() + "_pre.sql"); } } if (ignorarFecha || Diferencia.TotalHours > 1) { // Lázaro es más nuevo que la BD por más de 1 hora Progreso.ChangeStatus("Verificando estructuras"); this.CheckAndUpdateDataBaseStructure(Conn, false, Progreso); if (noTocarDatos == false) { this.CurrentConfig.WriteGlobalSetting("Sistema.DB.VersionEstructura", Lfx.Types.Formatting.FormatDateTimeSql(FechaLazaroExe.ToUniversalTime())); } } if (noTocarDatos == false && VersionActual < VersionUltima && VersionActual > 0) { for (int i = VersionActual + 1; i <= VersionUltima; i++) { Progreso.ChangeStatus("Post-actualización " + i.ToString()); InyectarSqlDesdeRecurso(Conn, @"Data.Struct.db_upd" + i.ToString() + "_post.sql"); this.CurrentConfig.WriteGlobalSetting("Sistema.DB.Version", i); } } Lfx.Workspace.Master.CurrentConfig.WriteGlobalSetting("Sistema.VerificarVersionBd.Inicio", "0"); Progreso.End(); } }