private static void InyectarSqlDesdeRecurso(Lfx.Data.IConnection 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.ExecuteNonQuery(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.ExecuteNonQuery(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="connection">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.IConnection connection, bool omitPreAndPostSql, Lfx.Types.OperationProgress progreso) { progreso.ChangeStatus("Verificando estructuras de datos"); bool MustEnableConstraints = false; if (connection.ConstraintsEnabled) { connection.EnableConstraints(false); MustEnableConstraints = true; } if (omitPreAndPostSql == false) { progreso.ChangeStatus("Ejecutando guión previo..."); InyectarSqlDesdeRecurso(connection, @"Data.Struct.db_upd_pre.sql"); } //Primero borro claves foráneas (deleteOnly = true) progreso.ChangeStatus("Eliminando reglas obsoletas..."); connection.SetConstraints(Lfx.Workspace.Master.Structure.Constraints, true); try { connection.ExecuteNonQuery("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); connection.SetTableStructure(Tab); } //Ahora creo claves nuevas (deleteOnly = false) progreso.ChangeStatus("Estableciendo reglas de integridad"); try { connection.ExecuteNonQuery("FLUSH TABLES"); } catch { // No tengo permiso... no importa } connection.SetConstraints(Lfx.Workspace.Master.Structure.Constraints, false); if (omitPreAndPostSql == false) { progreso.ChangeStatus("Ejecutando guión posterior..."); InyectarSqlDesdeRecurso(connection, @"Data.Struct.db_upd_post.sql"); } if (MustEnableConstraints) { connection.EnableConstraints(true); } }
/// <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.IConnection Conn = Lfx.Workspace.Master.GetNewConnection("Verificar estructura de la base de datos") as Lfx.Data.IConnection) { 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; } var 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") { 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.ExecuteNonQuery("FLUSH TABLES"); } catch (Exception ex) { // No tengo permiso... no importa Log.Warn("No se pudo hacer FLUSH TABLES", ex); } 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(); } }
protected void Bootstrap() { if (Lfx.Data.DatabaseCache.DefaultCache == null) { Lfx.Data.DatabaseCache.DefaultCache = new Lfx.Data.DatabaseCache(m_MasterConnection); } if (this.MasterConnection == null) { switch (this.CurrentConfig.ReadLocalSettingString(@"Data", "ConnectionType", "mysql")) { case "odbc": Lfx.Data.DatabaseCache.DefaultCache.AccessMode = Lfx.Data.AccessModes.Odbc; break; case "myodbc": case "mysql": Lfx.Data.DatabaseCache.DefaultCache.AccessMode = Lfx.Data.AccessModes.MySql; break; case "npgsql": Lfx.Data.DatabaseCache.DefaultCache.AccessMode = Lfx.Data.AccessModes.Npgsql; break; case "mssql": Lfx.Data.DatabaseCache.DefaultCache.AccessMode = Lfx.Data.AccessModes.MSSql; break; case "sqlite": Lfx.Data.DatabaseCache.DefaultCache.AccessMode = Lfx.Data.AccessModes.SQLite; break; } } if (this.ConnectionParameters == null) { this.ConnectionParameters = new ConnectionParameters() { ServerName = this.CurrentConfig.ReadLocalSettingString("Data", "DataSource", "localhost"), DatabaseName = this.CurrentConfig.ReadLocalSettingString("Data", "DatabaseName", "lazaro"), UserName = this.CurrentConfig.ReadLocalSettingString("Data", "User", "lazaro"), Password = this.CurrentConfig.ReadLocalSettingString("Data", "Password", string.Empty) }; //Lfx.Data.DatabaseCache.DefaultCache.ServerName = this.CurrentConfig.ReadLocalSettingString("Data", "DataSource", "localhost"); //Lfx.Data.DatabaseCache.DefaultCache.DatabaseName = this.CurrentConfig.ReadLocalSettingString("Data", "DatabaseName", "lazaro"); //Lfx.Data.DatabaseCache.DefaultCache.UserName = this.CurrentConfig.ReadLocalSettingString("Data", "User", "lazaro"); //Lfx.Data.DatabaseCache.DefaultCache.Password = this.CurrentConfig.ReadLocalSettingString("Data", "Password", string.Empty); //Lfx.Data.DatabaseCache.DefaultCache.Pooling = this.CurrentConfig.ReadLocalSettingInt("Data", "Pooling", 1) != 0; } var IpLocal1 = new System.Text.RegularExpressions.Regex(@"^192\.\d{1,3}\.\d{1,3}\.\d{1,3}$"); var IpLocal2 = new System.Text.RegularExpressions.Regex(@"^10\.\d{1,3}\.\d{1,3}\.\d{1,3}$"); if (Lfx.Workspace.Master.ConnectionParameters.ServerName.Contains(".") == false || IpLocal1.IsMatch(Lfx.Workspace.Master.ConnectionParameters.ServerName) || IpLocal2.IsMatch(Lfx.Workspace.Master.ConnectionParameters.ServerName)) { Lfx.Data.DatabaseCache.DefaultCache.SlowLink = false; } else { Lfx.Data.DatabaseCache.DefaultCache.SlowLink = true; } if (m_MasterConnection == null) { m_MasterConnection = this.GetNewConnection(this.Name) as Lfx.Data.IConnection; m_MasterConnection.RequiresTransaction = false; Lfx.Data.DatabaseCache.DefaultCache.Connection = m_MasterConnection; } }