using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using FirebirdSql.Data.FirebirdClient; using System.Data.SqlClient; using System.Text; using System.Threading; using System.Text.RegularExpressions; namespace ToMSSQL { /// /// Summary description for Form1. /// public class Form1 : System.Windows.Forms.Form { /// /// Required designer variable. /// private System.ComponentModel.Container components = null; private System.Windows.Forms.Button btnImport; private System.Windows.Forms.Button btnCancel; private Infragistics.Win.Misc.UltraLabel ultraLabel1; private Infragistics.Win.Misc.UltraLabel ultraLabel2; private Infragistics.Win.UltraWinEditors.UltraTextEditor edFBConnect; private Infragistics.Win.UltraWinEditors.UltraTextEditor edMSConnect; private Infragistics.Win.UltraWinProgressBar.UltraProgressBar pgCurrentOp; private System.Windows.Forms.Button btnTest; private BackgroundWorker bw; private Infragistics.Win.UltraWinProgressBar.UltraProgressBar pgOverall; public Form1() { // // Required for Windows Form Designer support // InitializeComponent(); // // TODO: Add any constructor code after InitializeComponent call // } /// /// Clean up any resources being used. /// protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1)); this.pgCurrentOp = new Infragistics.Win.UltraWinProgressBar.UltraProgressBar(); this.btnImport = new System.Windows.Forms.Button(); this.btnCancel = new System.Windows.Forms.Button(); this.edFBConnect = new Infragistics.Win.UltraWinEditors.UltraTextEditor(); this.edMSConnect = new Infragistics.Win.UltraWinEditors.UltraTextEditor(); this.ultraLabel1 = new Infragistics.Win.Misc.UltraLabel(); this.ultraLabel2 = new Infragistics.Win.Misc.UltraLabel(); this.pgOverall = new Infragistics.Win.UltraWinProgressBar.UltraProgressBar(); this.btnTest = new System.Windows.Forms.Button(); this.bw = new System.ComponentModel.BackgroundWorker(); ((System.ComponentModel.ISupportInitialize)(this.edFBConnect)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.edMSConnect)).BeginInit(); this.SuspendLayout(); // // pgCurrentOp // this.pgCurrentOp.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.pgCurrentOp.Location = new System.Drawing.Point(1, 191); this.pgCurrentOp.Name = "pgCurrentOp"; this.pgCurrentOp.Size = new System.Drawing.Size(665, 27); this.pgCurrentOp.Step = 1; this.pgCurrentOp.TabIndex = 0; this.pgCurrentOp.Text = "[Formatted]"; this.pgCurrentOp.Visible = false; // // btnImport // this.btnImport.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.btnImport.Image = ((System.Drawing.Image)(resources.GetObject("btnImport.Image"))); this.btnImport.Location = new System.Drawing.Point(569, 225); this.btnImport.Name = "btnImport"; this.btnImport.Size = new System.Drawing.Size(90, 40); this.btnImport.TabIndex = 28; this.btnImport.Visible = false; this.btnImport.Click += new System.EventHandler(this.btnImport_Click); // // btnCancel // this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.btnCancel.Image = ((System.Drawing.Image)(resources.GetObject("btnCancel.Image"))); this.btnCancel.Location = new System.Drawing.Point(8, 227); this.btnCancel.Name = "btnCancel"; this.btnCancel.Size = new System.Drawing.Size(94, 40); this.btnCancel.TabIndex = 27; this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); // // edFBConnect // this.edFBConnect.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.edFBConnect.Location = new System.Drawing.Point(2, 36); this.edFBConnect.Name = "edFBConnect"; this.edFBConnect.Size = new System.Drawing.Size(665, 24); this.edFBConnect.TabIndex = 29; this.edFBConnect.Text = "ServerType=1;DataBase=C:\\Program Files\\Ground Zero Tech-Works Inc\\AyaNova 3\\AYANO" + "VA.FDB;Dialect=3;"; this.edFBConnect.ValueChanged += new System.EventHandler(this.edFBConnect_ValueChanged); // // edMSConnect // this.edMSConnect.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.edMSConnect.Location = new System.Drawing.Point(2, 110); this.edMSConnect.Name = "edMSConnect"; this.edMSConnect.Size = new System.Drawing.Size(663, 24); this.edMSConnect.TabIndex = 30; this.edMSConnect.Text = "Server=COMPUTERNAME\\SQLExpress;initial catalog=master;User Id=sa; Password=PASSWO" + "RD;"; this.edMSConnect.ValueChanged += new System.EventHandler(this.edMSConnect_ValueChanged); // // ultraLabel1 // this.ultraLabel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.ultraLabel1.Location = new System.Drawing.Point(2, 3); this.ultraLabel1.Name = "ultraLabel1"; this.ultraLabel1.Size = new System.Drawing.Size(665, 27); this.ultraLabel1.TabIndex = 31; this.ultraLabel1.Text = "Firebird database connection string:"; // // ultraLabel2 // this.ultraLabel2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.ultraLabel2.Location = new System.Drawing.Point(2, 77); this.ultraLabel2.Name = "ultraLabel2"; this.ultraLabel2.Size = new System.Drawing.Size(665, 27); this.ultraLabel2.TabIndex = 32; this.ultraLabel2.Text = "Microsoft SQL database connection string:"; // // pgOverall // this.pgOverall.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.pgOverall.Location = new System.Drawing.Point(1, 156); this.pgOverall.Name = "pgOverall"; this.pgOverall.Size = new System.Drawing.Size(665, 27); this.pgOverall.Step = 1; this.pgOverall.TabIndex = 33; this.pgOverall.Text = "[Formatted]"; this.pgOverall.Visible = false; // // btnTest // this.btnTest.Location = new System.Drawing.Point(244, 232); this.btnTest.Name = "btnTest"; this.btnTest.Size = new System.Drawing.Size(271, 26); this.btnTest.TabIndex = 34; this.btnTest.Text = "Open database connections"; this.btnTest.Click += new System.EventHandler(this.btnTest_Click); // // bw // this.bw.WorkerReportsProgress = true; this.bw.WorkerSupportsCancellation = true; this.bw.DoWork += new System.ComponentModel.DoWorkEventHandler(this.bw_DoWork); this.bw.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.bw_ProgressChanged); this.bw.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.bw_RunWorkerCompleted); // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(6, 15); this.CancelButton = this.btnCancel; this.ClientSize = new System.Drawing.Size(674, 268); this.ControlBox = false; this.Controls.Add(this.btnTest); this.Controls.Add(this.pgOverall); this.Controls.Add(this.ultraLabel2); this.Controls.Add(this.ultraLabel1); this.Controls.Add(this.edMSConnect); this.Controls.Add(this.edFBConnect); this.Controls.Add(this.btnImport); this.Controls.Add(this.btnCancel); this.Controls.Add(this.pgCurrentOp); this.MinimumSize = new System.Drawing.Size(0, 265); this.Name = "Form1"; this.Text = "FireBird to SQL Migrator"; this.Load += new System.EventHandler(this.Form1_Load); ((System.ComponentModel.ISupportInitialize)(this.edFBConnect)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.edMSConnect)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } #endregion /// /// The main entry point for the application. /// [STAThread] static void Main() { Application.Run(new Form1()); } // __ _ _ ___ ____ __ __ __ __ __ ___ ___ // / _)( )( )/ __)(_ _)/ \( \/ ) / _)/ \( \( _) // ( (_ )()( \__ \ )( ( () )) ( ( (_( () )) ) )) _) // \__) \__/ (___/ (__) \__/(_/\/\_) \__)\__/(___/(___) //************************************************************ FbConnection fbcn = null; System.Data.SqlClient.SqlConnection mscn=null; //private Thread tr; private void btnCancel_Click(object sender, System.EventArgs e) { //if(tr!=null && tr.IsAlive) // tr.Abort(); bw.CancelAsync(); this.Close(); } private void btnImport_Click(object sender, System.EventArgs e) { DialogResult result=MessageBox.Show( "WARNING: If you proceed a new database called \"AyaNova\" \r\n"+ "will be created on the Microsoft SQL server you have indicated.\r\n\r\n" + "If there is an existing AyaNova database on that server it will be\r\n" + "erased prior to importing data from the Firebird AyaNova database.\r\n\r\n"+ "There is no way to reverse this process once it has started.\r\n\r\n"+ "Are you certain you wish to proceed?","Warning",MessageBoxButtons.YesNo, MessageBoxIcon.Warning,MessageBoxDefaultButton.Button2); if (result != DialogResult.Yes) return; btnImport.Visible = false; this.pgCurrentOp.Visible = true; this.pgOverall.Visible = true; bw.RunWorkerAsync(); //tr = new Thread(new ThreadStart(this.DoImport)); //tr.IsBackground = true; //tr.Start(); } public static string DisplayVersion(Version fileVersion)//case 2003 { return fileVersion.Major.ToString() + "." + fileVersion.Minor.ToString(); } private void Form1_Load(object sender, System.EventArgs e) { System.Reflection.Assembly a = System.Reflection.Assembly.GetExecutingAssembly(); System.Text.StringBuilder sb = new StringBuilder(); sb.Append("AyaNovaź FireBird to MSSQL migrator "); sb.Append(DisplayVersion(a.GetName().Version)); sb.Append(" "); System.Diagnostics.FileVersionInfo fileVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(a.Location); int nHotFix = fileVersion.FileBuildPart;//case 2003 if (nHotFix > 0) sb.AppendLine("(Patch " + nHotFix.ToString() + ")"); this.Text = sb.ToString(); //Case 642 so that it matches the new db location this.edFBConnect.Text="ServerType=1;DataBase=" + Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\AyaNovaData\\AYANOVA.FDB;Dialect=3;"; #if(DEBUG) //this.edFBConnect.Text = @"ServerType=1;DataBase=C:\data\AyaNova\database\AYANOVA.FDB;Dialect=3;"; //this.edMSConnect.Text = @"Server=VIRTDEVJOHN;initial catalog=master;User Id=sa; Password=abraxis;"; this.edFBConnect.Text = @"ServerType=1;DataBase=C:\data\AyaNova\database\ET_BAD_ID_AYANOVA.FDB;Dialect=3;"; this.edMSConnect.Text = @"Server=7DEVTEST-PC\SQLEXPRESS;initial catalog=master;User Id=sa; Password=abraxis;"; #endif } #region Create sql db private void CreateSQLDatabase(string sConnection, bool bDeleteExisting) { //this.pgCurrentOp.Maximum=100; //this.pgCurrentOp.Text="Create SQL database [Formatted]"; //this.pgCurrentOp.Value=10; Report(10, -1, "Connecting to MSSQL server", ""); mscn = new SqlConnection(sConnection); SqlCommand cm = new SqlCommand(); cm.Connection=mscn; try { mscn.Open(); if(bDeleteExisting) { //Delete if present cm.CommandText=("IF EXISTS (SELECT name FROM sysdatabases " + "WHERE name = N'AyaNova') DROP DATABASE AyaNova"); Report(20, -1, "Deleting existing AyaNova on MSSQL (if present)", ""); cm.ExecuteNonQuery(); } //this.pgCurrentOp.Value=50; //Create new Report(50, -1, "Creating new AyaNova on MSSQL", ""); cm.CommandText=" CREATE DATABASE AyaNova "; cm.ExecuteNonQuery(); } catch { throw; } finally { mscn.Close(); } //this.pgCurrentOp.Value=100; Report(100, -1, "Created new AyaNova on MSSQL", ""); return; } #endregion #region Tables private void MigrateTables() { SqlCommand cm = new SqlCommand(); cm.Connection=mscn; StringBuilder q=new StringBuilder(); DataTable t=fbcn.GetSchema("Tables", new string[] { null, null,null, "TABLE" }); //this.pgCurrentOp.Value=0; double nTotalRows = t.Rows.Count; double nCurrentRow = 0; int nProgress = 0; //pgCurrentOp.Maximum=t.Rows.Count; bool bHasIdentity=false;//flag that table being processed has an identity column (hard coded) string sIdentityColumnName=""; //iterate all tables foreach(DataRow drTable in t.Rows) { //check for current table //requiring an identity column set switch(drTable["TABLE_NAME"].ToString()) { case "APARTINVENTORYADJUSTMENT": sIdentityColumnName="AADJUSTMENTNUMBER"; bHasIdentity=true; break; case "APURCHASEORDER": sIdentityColumnName="APONUMBER"; bHasIdentity=true; break; case "AWORKORDERPREVENTIVEMAINTENANCE": sIdentityColumnName="APREVENTIVEMAINTENANCENUMBER"; bHasIdentity=true; break; case "AWORKORDERQUOTE": sIdentityColumnName="AQUOTENUMBER"; bHasIdentity=true; break; case "AWORKORDERSERVICE": sIdentityColumnName="ASERVICENUMBER"; bHasIdentity=true; break; default: bHasIdentity=false; sIdentityColumnName=""; break; } nCurrentRow++; nProgress = (int)((nCurrentRow / nTotalRows) * 100); Report(nProgress, -1, "Table " + drTable["TABLE_NAME"].ToString(), ""); //this.pgCurrentOp.Text="Create "+ drTable["TABLE_NAME"].ToString()+ " [Formatted]"; q.Append("CREATE TABLE "); q.Append(drTable["TABLE_NAME"].ToString()); q.Append(" ("); DataTable tColumns= fbcn.GetSchema("Columns", new string[] { null,null, drTable["TABLE_NAME"].ToString() }); foreach(DataRow drColumns in tColumns.Rows) { q.Append(drColumns["COLUMN_NAME"].ToString()); q.Append(" "); string sType=""; if(drColumns["DOMAIN_NAME"]!=System.DBNull.Value) { sType=drColumns["DOMAIN_NAME"].ToString(); } else sType=drColumns["COLUMN_DATA_TYPE"].ToString(); switch(sType) { //DOMAIN TYPES case "D_GUID": q.Append("uniqueidentifier"); break; case "D_MEMO": q.Append("ntext"); break; case "D_BOOL": q.Append("bit"); break; //STANDARD TYPES case "smallint": q.Append("smallint"); break; case "varchar": q.Append("nvarchar"); q.Append(" ("); q.Append(drColumns["COLUMN_SIZE"].ToString()); q.Append(")"); break; case "char": q.Append("char"); q.Append(" ("); q.Append(drColumns["COLUMN_SIZE"].ToString()); q.Append(")"); break; case "timestamp": q.Append("datetime"); break; case "decimal": q.Append("decimal (19,5)"); break; case "integer": q.Append("int"); break; case "bigint": q.Append("bigint"); break; case "blob": q.Append("image"); break; default: throw new System.ApplicationException("Migrate tables: Unknown type: " + sType + "\r\n\r\nIN: " + q.ToString()); } //Set IDENTITY IF applicable if (bHasIdentity && drColumns["COLUMN_NAME"].ToString() == sIdentityColumnName) q.Append(" IDENTITY "); //Nullable? if (((bool)drColumns["IS_NULLABLE"]) == false)//Case 649 Used to be 0 now is boolean false q.Append(" NOT NULL"); else q.Append(" NULL"); q.Append(", "); } q.Append(" )"); cm.CommandText=q.ToString(); cm.ExecuteNonQuery(); q.Length=0; //pgCurrentOp.PerformStep(); } Report(100, -1, "Finished", "Migrating table structure"); } #endregion tables #region Copy data private void CopyData() { SqlCommand cm = new SqlCommand(); cm.Connection=mscn; bool bHasIdentity=false; DataTable t=fbcn.GetSchema("Tables", new string[] { null, null,null, "TABLE" }); //this.pgCurrentOp.Value=0; //pgCurrentOp.Maximum=t.Rows.Count; double nTotalRows = t.Rows.Count; double nCurrentRow = 0; int nProgress = 0; foreach(DataRow drTable in t.Rows) { //this.pgCurrentOp.Text="Migrate "+ drTable["TABLE_NAME"].ToString()+ " [Formatted]"; nCurrentRow++; nProgress = (int)((nCurrentRow / nTotalRows) * 100); Report(nProgress, -1, "Table " + drTable["TABLE_NAME"].ToString(), ""); //check for current table //requiring an identity column set switch(drTable["TABLE_NAME"].ToString()) { case "APARTINVENTORYADJUSTMENT": bHasIdentity=true; break; case "APURCHASEORDER": bHasIdentity=true; break; case "AWORKORDERPREVENTIVEMAINTENANCE": bHasIdentity=true; break; case "AWORKORDERQUOTE": bHasIdentity=true; break; case "AWORKORDERSERVICE": bHasIdentity=true; break; default: bHasIdentity=false; break; } FbDataReader dr=new FbCommand("SELECT * FROM " + drTable["TABLE_NAME"].ToString(),fbcn).ExecuteReader(); //Set allow identity insert on? if(bHasIdentity) { cm.CommandText="SET IDENTITY_INSERT " +drTable["TABLE_NAME"].ToString()+" ON; " + GetInsertSQL(dr,drTable["TABLE_NAME"].ToString()); } else cm.CommandText=GetInsertSQL(dr,drTable["TABLE_NAME"].ToString()); SetParameters(ref cm,dr); while(dr.Read()) { InsertRow(ref cm,dr); //pgCurrentOp.PerformStep(); } dr.Close(); } Report(100, -1, "Finished", "Copying table data"); } private void InsertRow(ref SqlCommand cm,FbDataReader dr) { foreach(DataRow drTable in dr.GetSchemaTable().Rows) { if ((drTable["ProviderType"].ToString() == "3" || drTable["ProviderType"].ToString() == "4" /*case 649 changed provider type?*/)&& drTable["ColumnSize"].ToString() == "38") {//it's a guid object o=dr[drTable["ColumnName"].ToString()]; if (o == System.DBNull.Value) cm.Parameters["@p" + drTable["ColumnName"].ToString()].Value = System.DBNull.Value; else { //case 3157 //swapped this line for everything in this else block below to handle and properly report bad Guid's //cm.Parameters["@p" + drTable["ColumnName"].ToString()].Value = new Guid(dr[drTable["ColumnName"].ToString()].ToString()); Guid newGuid; String stringGuid = dr[drTable["ColumnName"].ToString()].ToString(); if (Guid.TryParse(stringGuid, out newGuid)) { //success cm.Parameters["@p" + drTable["ColumnName"].ToString()].Value = newGuid; } else { //FAIL, report all info possible: System.Text.StringBuilder sb = new StringBuilder(); sb.AppendLine("Fatal error during import in stage \"Copying table data::InsertRow\""); sb.AppendLine("Bad GUID value can't be interpreted"); sb.AppendLine("==================================="); sb.AppendLine("Bad value: '"+stringGuid + "'"); sb.AppendLine("In column: '" + drTable["ColumnName"].ToString() + "'"); sb.AppendLine("In table: '" + drTable["BaseTableName"].ToString() + "'"); sb.AppendLine("==================================="); sb.AppendLine("SQL import command would have been:"); sb.AppendLine(cm.CommandText); sb.AppendLine("==================================="); throw new ApplicationException(sb.ToString()); } } } else if (drTable["DataType"].ToString() == "System.DateTime") { //case 1831 object o=dr[drTable["ColumnName"].ToString()]; DateTime dt = DateTime.MinValue; if (o != System.DBNull.Value) { dt = (DateTime)o; if (dt.Year < 1754 || dt.Year > 9999) dt = new DateTime(1966, 1, 1); cm.Parameters["@p" + drTable["ColumnName"].ToString()].Value = dt; } else cm.Parameters["@p" + drTable["ColumnName"].ToString()].Value = o; } else cm.Parameters["@p"+drTable["ColumnName"].ToString()].Value=dr[drTable["ColumnName"].ToString()]; } try { cm.ExecuteNonQuery(); } catch (Exception ex) { System.Text.StringBuilder sb = new StringBuilder(); sb.AppendLine("Fatal error during import in stage \"Copying table data\""); sb.AppendLine("Insert command that failed was: "); sb.AppendLine("==================================="); sb.AppendLine(cm.CommandText); sb.AppendLine("==================================="); sb.AppendLine("PARAMETERS ARE:"); foreach (SqlParameter p in cm.Parameters) sb.AppendLine(p.ParameterName + " - " + p.Value.ToString()); sb.AppendLine("==================================="); throw new ApplicationException(sb.ToString(), ex); } } //Create the paramaters collection private void SetParameters(ref SqlCommand cm,FbDataReader dr) { cm.Parameters.Clear(); foreach(DataRow drTable in dr.GetSchemaTable().Rows) { string sName="@p"+drTable["ColumnName"]; switch(drTable["DataType"].ToString()) { case "System.Decimal": cm.Parameters.Add(sName,SqlDbType.Decimal); break; case "System.String": if (drTable["ProviderType"].ToString() == "15" || drTable["ProviderType"].ToString() == "16") { //ordinary string cm.Parameters.Add(sName,SqlDbType.NVarChar); } else if (drTable["ProviderType"].ToString() == "12" || drTable["ProviderType"].ToString() == "13") { //Ntext cm.Parameters.Add(sName,SqlDbType.NText); } else if (drTable["ProviderType"].ToString() == "3" || drTable["ProviderType"].ToString() == "4")//case 649 { if(drTable["ColumnSize"].ToString()=="38")//guid are always 38 cm.Parameters.Add(sName,SqlDbType.UniqueIdentifier);//Guid else//it's a standard char field (i.e. login and password hashes in user table cm.Parameters.Add(sName,SqlDbType.Char); } break; case "System.DateTime": cm.Parameters.Add(sName,SqlDbType.DateTime); break; case "System.Int16": cm.Parameters.Add(sName,SqlDbType.SmallInt); break; case "System.Int32": cm.Parameters.Add(sName,SqlDbType.Int); break; case "System.Int64": cm.Parameters.Add(sName,SqlDbType.BigInt); break; case "System.Byte[]": cm.Parameters.Add(sName,SqlDbType.Image); break; default: throw new ApplicationException("SetParameters UKNOWN TYPE: " + sName + " - " + drTable["DataType"].ToString()); } } } //Inserts a row into the target table private string GetInsertSQL(FbDataReader dr, string sTableName) { StringBuilder q=new StringBuilder(); q.Append("INSERT INTO "); q.Append(sTableName); q.Append(" ("); //Field names foreach(DataRow drTable in dr.GetSchemaTable().Rows) { q.Append(drTable["ColumnName"].ToString()); q.Append(","); } q.Length=q.Length-1;//ditch the comma q.Append(") VALUES ("); foreach(DataRow drTable in dr.GetSchemaTable().Rows) { q.Append("@p"); q.Append(drTable["ColumnName"].ToString()); q.Append(","); } q.Length=q.Length-1;//ditch the comma q.Append(")"); return q.ToString(); } #endregion copy data #region primary keys private void MigratePK() { SqlCommand cm = new SqlCommand(); cm.Connection=mscn; StringBuilder q=new StringBuilder(); DataTable t=fbcn.GetSchema("PrimaryKeys"); bool bDoneLocalizedText=false; //this.pgCurrentOp.Value=0; //pgCurrentOp.Maximum=t.Rows.Count; double nTotalRows = t.Rows.Count; double nCurrentRow = 0; int nProgress = 0; foreach(DataRow drTable in t.Rows) { //this.pgCurrentOp.Text="Create primary key "+ drTable["TABLE_NAME"].ToString() + "." + drTable["COLUMN_NAME"].ToString()+ " [Formatted]"; nCurrentRow++; nProgress = (int)((nCurrentRow / nTotalRows) * 100); Report(nProgress, -1, "Key " + drTable["TABLE_NAME"].ToString() + "." + drTable["COLUMN_NAME"].ToString(), ""); q.Length=0; q.Append("ALTER TABLE "); q.Append(drTable["TABLE_NAME"].ToString()); q.Append(" ADD PRIMARY KEY NONCLUSTERED ("); if( drTable["TABLE_NAME"].ToString()=="ALOCALIZEDTEXT") { if(bDoneLocalizedText) continue; q.Append("AKEY, ALOCALE"); bDoneLocalizedText=true; } else q.Append(drTable["COLUMN_NAME"].ToString()); q.Append(" )"); cm.CommandText=q.ToString(); cm.ExecuteNonQuery(); //pgCurrentOp.PerformStep(); } Report(100, -1, "Finished", ""); } #endregion primary keys #region Regular indexes private void MigrateIndexes() { SqlCommand cm = new SqlCommand(); cm.Connection=mscn; StringBuilder q=new StringBuilder(); //StringBuilder q2 = new StringBuilder();//Testing case 378 DataTable t = fbcn.GetSchema("IndexColumns");//changed case 649 new provider //this.pgCurrentOp.Value=0; //pgCurrentOp.Maximum=t.Rows.Count; double nTotalRows = t.Rows.Count; double nCurrentRow = 0; int nProgress = 0; foreach(DataRow drTable in t.Rows) { q.Length=0; //pgCurrentOp.PerformStep(); q.Append("CREATE INDEX "); q.Append(drTable["INDEX_NAME"].ToString()); q.Append(" ON "); //Weed out undesireables such as compound indexes //because they are processed through here as two separate calls for the //same index throwing a sqlexecption and must be added later down if (drTable["INDEX_NAME"].ToString().StartsWith("IDX6_") ||//case 1303 v6 indexes which are now created separately below drTable["INDEX_NAME"].ToString().StartsWith("RDB$") ||//system index drTable["INDEX_NAME"].ToString().StartsWith("PK") || drTable["INDEX_NAME"].ToString().StartsWith("FK") || drTable["TABLE_NAME"].ToString()=="ALOCALIZEDTEXT" || drTable["TABLE_NAME"].ToString()=="ANOTIFYSUBSCRIPTION" || drTable["INDEX_NAME"].ToString()=="USERCREDS" || drTable["INDEX_NAME"].ToString()=="IDX_AINTEGRATIONMAP2" )// continue; q.Append(drTable["TABLE_NAME"].ToString()); q.Append(" ( "); q.Append(drTable["COLUMN_NAME"].ToString()); q.Append(" ) "); //this.pgCurrentOp.Text="Create Index "+ drTable["TABLE_NAME"].ToString() + "." + drTable["INDEX_NAME"].ToString()+ " [Formatted]"; nCurrentRow++; nProgress = (int)((nCurrentRow / nTotalRows) * 100); Report(nProgress, -1, "Index " + drTable["TABLE_NAME"].ToString() + "." + drTable["INDEX_NAME"].ToString(), ""); cm.CommandText=q.ToString(); cm.ExecuteNonQuery(); //q2.Append("DDL(\"IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[" + drTable["TABLE_NAME"].ToString() + "]') AND name = N'" + drTable["INDEX_NAME"].ToString() + "') \" +\r\n" + // "\""+q+"\");\r\n"); //testing for case 378 } Report(0, -1, "Starting", "Migrating compound indexes"); //Add the compound indexes that couldn't be added before cm.CommandText="CREATE UNIQUE INDEX IX_ANOTIFYSUBSCRIPTIONMUSTBEUNI ON ANOTIFYSUBSCRIPTION (AUSERID, AROOTOBJECTTYPE, AEVENTTYPE, AGUIDVALUE)"; cm.ExecuteNonQuery(); cm.CommandText="CREATE UNIQUE INDEX USERCREDS ON AUSER (ALOGIN, APASSWORD)"; cm.ExecuteNonQuery(); try { //bug bug //case 329 got missed here reared it's ugly head 10 years later //cm.CommandText="CREATE UNIQUE INDEX IDX_AINTEGRATIONMAP2 ON AINTEGRATIONMAP(AROOTOBJECTID,AROOTOBJECTTYPE)"; cm.CommandText = "CREATE UNIQUE INDEX IDX_AINTEGRATIONMAP2 ON AINTEGRATIONMAP(AROOTOBJECTID,AROOTOBJECTTYPE,AINTEGRATIONID)"; cm.ExecuteNonQuery(); } catch {} //case 1303 v6 indexes //in a try block in case they already exist somehow which should be impossible but who friggin knows //what users will do //ONLY run this on a schema that is 92 or higher. Anything older will get these in the AyaNova schema update //this means we need to determine the schema early on here if (mDBSchemaVersion > 91) { try { //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DDL(cm, "CREATE CLUSTERED INDEX IDX6_ASERVICEBANK_CREAT ON dbo.ASERVICEBANK (ACREATED) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AVENDOR_CVR ON dbo.AVENDOR (AID)INCLUDE (ANAME) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AUSRREGION ON dbo.AUSER (AID) INCLUDE ( AREGIONID) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_APROJECTIDNAME ON dbo.APROJECT (AID) INCLUDE (ANAME) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_ACLIENT_CLIENTSELECTOR ON dbo.ACLIENT (ANAME) INCLUDE ( AID, AACTIVE, AREGIONID) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_ACLIENTDISPZN ON dbo.ACLIENT (AID,ADISPATCHZONEID) INCLUDE (ANAME) "); DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWO ON dbo.AWORKORDER (ACREATED) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AWORKORDER_CVR ON dbo.AWORKORDER " + "( " + " AWORKORDERTYPE, " + " AID, " + " APROJECTID, " + " AFROMPMID, " + " AFROMQUOTEID, " + " AWORKORDERCATEGORYID, " + " ACLIENTID " + ") " + "INCLUDE ( ACREATED, " + "AMODIFIED, " + "AINTERNALREFERENCENUMBER, " + "ACUSTOMERREFERENCENUMBER, " + "AONSITE, " + "ACUSTOMERCONTACTNAME, " + "ASUMMARY, " + "ACLOSED, " + "ASERVICECOMPLETED) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AUNITMODEL_CVR2 ON dbo.AUNITMODEL (AUNITMODELCATEGORYID, AID, AVENDORID) INCLUDE ( ANAME) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AUNITMODELIDVEND ON dbo.AUNITMODEL (AID,AVENDORID) INCLUDE (ANAME,AMODELNUMBER) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AUNIT_CVR ON dbo.AUNIT (AID,AUNITMODELID) INCLUDE (ASERIAL,APURCHASEDDATE,ATEXT1,ATEXT2,ATEXT3,ATEXT4) "); DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOITEM ON dbo.AWORKORDERITEM (ACREATED) "); DDL(cm, "CREATE CLUSTERED INDEX IDX6_ALOCALIZEDTEXT_CL ON dbo.ALOCALIZEDTEXT (ALOCALE,AKEY) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_ACLIENTNOTIFYEVENT_CREAT ON dbo.ACLIENTNOTIFYEVENT (ACREATED) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AADDRESS_CVR ON dbo.AADDRESS (AROOTOBJECTID,AADDRESSTYPE) " + "INCLUDE ( ADELIVERYADDRESS,ACITY,ASTATEPROV,ACOUNTRYCODE,ACOUNTRY,APOSTAL,ALONGITUDE,ALATITUDE) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AGRIDFILTER_NAME ON dbo.AGRIDFILTER (ANAME) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_ASEARCHKEY ON dbo.ASEARCHKEY (AWORDID,ASOURCEOBJECTTYPE,ASOURCEOBJECTID) "); DDL(cm, "CREATE CLUSTERED INDEX IDX6_ASEARCHDICTIONARY ON dbo.ASEARCHDICTIONARY (AWORD) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_ASEARCHDICTIONARY_NONCLUST ON dbo.ASEARCHDICTIONARY (AWORD) "); DDL(cm, "CREATE CLUSTERED INDEX IDX6_ASCHEDULEMARKER_CVR ON dbo.ASCHEDULEMARKER (ASTARTDATE,ASTOPDATE) "); DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOIMISCEXP ON dbo.AWORKORDERITEMMISCEXPENSE (ACREATED) "); DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOILOA ON dbo.AWORKORDERITEMLOAN (ACREATED) "); DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOSVC ON dbo.AWORKORDERSERVICE (ACREATED) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AWORKORDERSERVICE_CVR ON dbo.AWORKORDERSERVICE (AWORKORDERID) " + "INCLUDE ( AWORKORDERSTATUSID,ASERVICEDATE,AINVOICENUMBER,ASERVICENUMBER,ACLOSEBYDATE) "); DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOIOUT ON dbo.AWORKORDERITEMOUTSIDESERVICE (ACREATED) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AWOIOUTSIDESERVICECVR ON dbo.AWORKORDERITEMOUTSIDESERVICE (AWORKORDERITEMID,AVENDORSENTTOID,AVENDORSENTVIAID) " + "INCLUDE ( ARMANUMBER,ATRACKINGNUMBER,AREPAIRCOST,AREPAIRPRICE,ASHIPPINGCOST,ASHIPPINGPRICE,ADATESENT,ASENDERUSERID,ADATEETA,ADATERETURNED) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_ANOTIFYEVENT_APPLIESTO ON dbo.ANOTIFYEVENT (AAPPLIESTOUSERID) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_APART_4INVENT ON dbo.APART " + "(AID,APARTASSEMBLYID,APARTCATEGORYID,AALTERNATIVEWHOLESALERID,AWHOLESALERID,AMANUFACTURERID,APARTNUMBER,AACTIVE,ARETAIL,ACOST) " + "INCLUDE (ANAME,AUPC) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_APART_CVR ON dbo.APART (AID,APARTASSEMBLYID,APARTCATEGORYID,AMANUFACTURERID) " + "INCLUDE (ANAME,APARTNUMBER,AUPC) "); DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOIPRTRQST ON dbo.AWORKORDERITEMPARTREQUEST (ACREATED) "); DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOIPRT ON dbo.AWORKORDERITEMPART (ACREATED) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AWORKORDERITEMPARTCVR ON dbo.AWORKORDERITEMPART (AWORKORDERITEMID,APARTSERIALID,APARTWAREHOUSEID,APARTID) " + "INCLUDE (AID,AQUANTITY,ACOST,APRICE,ADISCOUNT,ADESCRIPTION,AUSED,ATAXPARTSALEID,AQUANTITYRESERVED) "); DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOITRVL ON dbo.AWORKORDERITEMTRAVEL (ACREATED) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AWORKORDERITEMTRAVEL_CVR ON dbo.AWORKORDERITEMTRAVEL (AWORKORDERITEMID) " + "INCLUDE (AID,AUSERID,ATRAVELSTARTDATE,ATRAVELSTOPDATE,ATRAVELRATEID,ATRAVELDETAILS,ATRAVELRATEQUANTITY,ANOCHARGEQUANTITY,ADISTANCE,ATAXRATESALEID) "); DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOISCHEDUSR ON dbo.AWORKORDERITEMSCHEDULEDUSER (ACREATED) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AWORKORDERITEMSCHEDULEDUSER_CVR ON dbo.AWORKORDERITEMSCHEDULEDUSER (AWORKORDERITEMID) " + "INCLUDE ( AID,AUSERID,AESTIMATEDQUANTITY,ASTARTDATE,ASTOPDATE,ASERVICERATEID) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_AWOISCHEDULEDUSER_CVR2 ON dbo.AWORKORDERITEMSCHEDULEDUSER (ASTOPDATE,ASTARTDATE,AWORKORDERITEMID) " + "INCLUDE ( AID,AUSERID) "); DDL(cm, "CREATE CLUSTERED INDEX IDX6_AWOILAB ON dbo.AWORKORDERITEMLABOR (ACREATED) "); DDL(cm, "CREATE NONCLUSTERED INDEX IDX6_APARTBYWAREHOUSEINVENTORY_APARTID ON dbo.APARTBYWAREHOUSEINVENTORY (APARTID) "); //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% } catch { } } Report(100, -1, "Finished", ""); } /// /// execute DDL statement /// /// public void DDL(SqlCommand cm, string sDDL) { cm.CommandText = sDDL; cm.ExecuteNonQuery(); } #endregion regular indexes #region Foreign keys private void MigrateFK() { SqlCommand cm = new SqlCommand(); cm.Connection=mscn; StringBuilder q=new StringBuilder(); //case 1401 DataTable t = GetForeignKeyColumns(fbcn); // DataTable t = fbcn.GetSchema("ForeignKeyColumns");//Case 649 double nTotalRows = t.Rows.Count; double nCurrentRow = 0; int nProgress = 0; foreach(DataRow drTable in t.Rows) { //Case 649 this block all column names in drTable new q.Length=0; nCurrentRow++; nProgress = (int)((nCurrentRow / nTotalRows) * 100); Report(nProgress, -1, "Foreign key " + drTable["COLUMN_NAME"].ToString() + "-" + drTable["REFERENCED_COLUMN_NAME"].ToString(), ""); q.Append("ALTER TABLE "); q.Append(drTable["TABLE_NAME"].ToString()); q.Append(" ADD CONSTRAINT "); q.Append(drTable["CONSTRAINT_NAME"].ToString()); q.Append(" FOREIGN KEY ("); q.Append(drTable["COLUMN_NAME"].ToString()); q.Append(") REFERENCES "); q.Append(drTable["REFERENCED_TABLE_NAME"].ToString()); q.Append(" ("); q.Append(drTable["REFERENCED_COLUMN_NAME"].ToString()); q.Append(")"); cm.CommandText=q.ToString(); cm.ExecuteNonQuery(); } Report(100, -1, "Finished", ""); } public DataTable GetForeignKeyColumns(FbConnection connection) { System.Text.StringBuilder sb = new StringBuilder(); DataTable dt = new DataTable(); dt.Columns.Add("TABLE_NAME", typeof(System.String)); dt.Columns.Add("CONSTRAINT_NAME", typeof(System.String)); dt.Columns.Add("COLUMN_NAME", typeof(System.String)); dt.Columns.Add("REFERENCED_TABLE_NAME", typeof(System.String)); dt.Columns.Add("REFERENCED_COLUMN_NAME", typeof(System.String)); foreach (DataRow row in connection.GetSchema("ForeignKeys").Rows) { var constraintName = (string)row["CONSTRAINT_NAME"]; var tableName = (string)row["TABLE_NAME"]; var referencedTableName = (string)row["REFERENCED_TABLE_NAME"]; // use this instead of connection.GetSchema("ForeignKeyColumns") until the bug has been corrected string commandText = @" SELECT null AS CONSTRAINT_CATALOG,null AS CONSTRAINT_SCHEMA,co.rdb$constraint_name AS CONSTRAINT_NAME, null AS TABLE_CATALOG,null AS TABLE_SCHEMA,co.rdb$relation_name AS TABLE_NAME, coidxseg.rdb$field_name AS COLUMN_NAME, null as REFERENCED_TABLE_CATALOG,null as REFERENCED_TABLE_SCHEMA,refco.rdb$relation_name AS REFERENCED_TABLE_NAME, refidxseg.rdb$field_name AS REFERENCED_COLUMN_NAME, coidxseg.rdb$field_position AS ORDINAL_POSITION FROM rdb$ref_constraints ref INNER JOIN rdb$relation_constraints co ON ref.rdb$constraint_name=co.rdb$constraint_name INNER JOIN rdb$index_segments coidxseg ON co.rdb$index_name=coidxseg.rdb$index_name INNER JOIN rdb$relation_constraints refco ON ref.rdb$const_name_uq=refco.rdb$constraint_name INNER JOIN rdb$index_segments refidxseg ON refco.rdb$index_name=refidxseg.rdb$index_name AND coidxseg.rdb$field_position=refidxseg.rdb$field_position WHERE co.rdb$relation_name=@p0 AND co.rdb$constraint_name=@p1 ORDER BY ref.rdb$constraint_name,coidxseg.rdb$field_position" ; // AND coidxseg.rdb$field_name = @p3", using (var cmd = connection.CreateCommand()) { cmd.CommandText = commandText; cmd.Parameters.Add( "@p0", FbDbType.Char, 31).Value = tableName; cmd.Parameters.Add( "@p1", FbDbType.Char, 31).Value = constraintName; //cmd.Parameters.Add("@p3", FbDbType.Char, 31).Value = fieldName; using (var reader = cmd.ExecuteReader()) while (reader.Read()) { DataRow dr = dt.NewRow(); dr["CONSTRAINT_NAME"] = reader.GetString(2); dr["TABLE_NAME"] = reader.GetString(5); dr["COLUMN_NAME"] = reader.GetString(6); dr["REFERENCED_TABLE_NAME"] = reader.GetString(9); dr["REFERENCED_COLUMN_NAME"] = reader.GetString(10); dt.Rows.Add(dr); // Debug.Assert(constraintName == reader.GetString(2 /*"CONSTRAINT_NAME"*/).TrimEnd()); //Debug.Assert(tableName == reader.GetString(5 /*"TABLE_NAME"*/).TrimEnd()); //6=COLUMN_NAME //Debug.Assert(referencedTableName == reader.GetString(9/*"REFERENCED_TABLE_NAME"*/).TrimEnd()); //10=REFERENCED_COLUMN_NAME } } } return dt; } #endregion foreign keys #region Test connections private bool TestSQLConnection(string sConnection) { if(this.edMSConnect.Text=="") { MessageBox.Show("A Microsoft SQL database connection string is required.\r\n"); return false; } if(this.edMSConnect.Text.IndexOf("master")==-1) { MessageBox.Show("The SQL server connection string doesn't appear to have the\r\n" + "required initial catalog set to the \"master\" database."); return false; } try { System.Data.SqlClient.SqlConnection cn=new SqlConnection(sConnection); cn.Open(); cn.Close(); } catch(Exception ex) { MessageBox.Show("SQL Connection failed\r\nCheck your connection string\r\nFull error was:\r\n" + ex.Message); return false; } return true; } private int mDBSchemaVersion=9999; private bool TestFBConnection(string sConnection) { if(this.edFBConnect.Text=="") { MessageBox.Show("A Firebird connection string is required.\r\n" + "(See AyaNova.Exe.Config file)"); return false; } try { FbConnection cn=new FbConnection(FixupFBConnectionString(sConnection)); cn.Open(); FbDataReader dr = new FbCommand("SELECT ADBSCHEMA FROM AGLOBALEX", cn).ExecuteReader(); if (dr.Read()) { mDBSchemaVersion = (int)dr[0]; dr.Close(); } cn.Close(); } catch(Exception ex) { MessageBox.Show("Firebird Connection failed\r\nCheck your connection string\r\nFull error was:\r\n" + ex.Message); return false; } return true; } private void btnTest_Click(object sender, System.EventArgs e) { MessageBox.Show("ToMSSQL will now attempt to open the databases\r\n" + "based on the connection strings you provided\r\n" + "If they are correct this should take less than a few seconds\r\n" + "If it takes longer the connection string is likely incorrect\r\n" + "wait for the error message to display which will indicate the problem"); Cursor.Current=Cursors.WaitCursor; if(TestSQLConnection(this.edMSConnect.Text) && TestFBConnection(FixupFBConnectionString(this.edFBConnect.Text))) { MessageBox.Show("Connections are good, you can now migrate data"); edFBConnect.ReadOnly=true; edMSConnect.ReadOnly=true; this.btnImport.Visible=true; this.btnTest.Visible=false; } } #endregion test connections private void edFBConnect_ValueChanged(object sender, System.EventArgs e) { this.btnImport.Visible=false; this.btnTest.Visible=true; } private void edMSConnect_ValueChanged(object sender, System.EventArgs e) { this.btnImport.Visible=false; this.btnTest.Visible=true; } private void bw_DoWork(object sender, DoWorkEventArgs e) { try { Report(0,0,"Connecting","Overall"); //bw.ReportProgress(0, //this.pgOverall.Text = "Overall [Formatted]"; //this.pgOverall.Value = 0; fbcn = new FbConnection(FixupFBConnectionString(this.edFBConnect.Text)); fbcn.Open(); //this.pgOverall.Value=1; CreateSQLDatabase(this.edMSConnect.Text, true); // this.pgOverall.Value = 2; Report(0, 1, "Switching to AyaNova on MSSQL", ""); mscn = new SqlConnection(this.edMSConnect.Text.Replace("master", "AyaNova")); mscn.Open(); //this.pgOverall.Value = 3; Report(100, 2, "Switched to AyaNova on MSSQL", ""); Report(0, 3, "Starting", "Migrating table structure"); MigrateTables(); //this.pgOverall.Value = 4; Report(0, 10, "Starting", "Copying table data"); CopyData(); //this.pgOverall.Value = 5; Report(0, 65, "Starting", "Migrating primary keys"); MigratePK(); //this.pgOverall.Value = 6; Report(0, 85, "Starting", "Migrating indexes"); MigrateIndexes(); //this.pgOverall.Value = 7; Report(0, 95, "Starting", "Migrating foreign keys"); MigrateFK(); Report(100, 100, "Finished", "Finished"); //this.pgOverall.Text = "Finished [Formatted]"; //this.pgOverall.Value = 8;// done! //this.pgCurrentOp.Value = pgCurrentOp.Maximum; //this.pgCurrentOp.Text = "Finished [Formatted]"; } catch(Exception ex) { throw ex; } finally { if (fbcn != null) fbcn.Close(); if (mscn != null) mscn.Close(); } } #region progress reporting public struct ProgressStruct { public string sCurrent; public int nCurrent; public string sOverall; public int nOverall; } private void Report(int current, int overall, string scurrent, string soverall) { ProgressStruct ps; ps.nCurrent = current; ps.nOverall = overall; ps.sCurrent = scurrent; ps.sOverall = soverall; bw.ReportProgress(1, ps); } private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e) { ProgressStruct ps = (ProgressStruct)e.UserState; if(ps.sOverall!="") this.pgOverall.Text = ps.sOverall + " [Formatted]"; if(ps.nOverall!=-1) this.pgOverall.Value = ps.nOverall; this.pgCurrentOp.Text = ps.sCurrent + " [Formatted]"; this.pgCurrentOp.Value = ps.nCurrent; } #endregion progress reporting private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Error != null) { System.Text.StringBuilder sb = new StringBuilder(); sb.AppendLine(e.Error.Message); sb.AppendLine(e.Error.StackTrace); if (e.Error.InnerException != null) { sb.AppendLine("Inner exception:"); sb.AppendLine(e.Error.InnerException.Message); sb.AppendLine(e.Error.InnerException.StackTrace); } CopyableMessageBox d = new CopyableMessageBox(sb.ToString()); d.ShowDialog(); } } //case 1400 private static string FixupFBConnectionString(string sConnect) { Regex regex = new Regex("User\\s*=", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled); if (!regex.IsMatch(sConnect)) sConnect = sConnect + "User=SYSDBA;"; return sConnect; } } }