前段時間做一個項目,因為其中數據庫有許多數據是初始化的數據, 為了便於部署.於是我在制作安裝程序的時候加入了 DB install的功能.
首先最好單獨創建一個DB install 的Class Library的Project.
Fileà NewàProjectàVisual C# à WindowsàClass Library
然後創建一個class, 命名為DBInstall.cs. 下面就是如何在這個class 中實現DB"安裝"的過程.
首先需要將 DBInstall 繼承 Installer class. 還需要加上[RunInstaller(true)]的attribute.
繼承
1[RunInstaller(true)] 2 3public partial class DBInstall : Installer 4
此時圖標會由變為, 說明這個class 已經成為了安裝的組件了.
然後就是 override Rollback, Uninstall, Install 三個方法:
Override Install Method
1 public override void Rollback(System.Collections.IDictionary savedState) 2 3 { 4 5 base.Rollback(savedState); 6 7 8 9 if (MessageBox.Show("Do you want to remove exist databases during rollback?", "Confirm", MessageBoxButtons.YesNo) 10 11 == DialogResult.Yes) 12 13 { 14 15 string dbname = "XXX"; //XXX 代表數據庫名稱 16 17 try 18 19 { 20 21 ExecuteSql("master", string.Format("DROP DATABASE [{0}]", dbname)); //回滾的時候刪除數據庫文件 22 23 } 24 25 catch 26 27 { 28 29 MessageBox.Show(string.Format("Can not delete [{0}] database. Please delete it by yourself."), dbname); 30 31 } 32 33 34 35 } 36 37 } 38 39 40 41 public override void Uninstall(System.Collections.IDictionary savedState) 42 43 { 44 45 base.Uninstall(savedState); 46 47 48 49 try 50 51 { 52 53 if (MessageBox.Show("Do you want to remove databases?", "Confirm", MessageBoxButtons.YesNo) 54 55 == DialogResult.Yes) 56 57 { 58 59 DBConfig dbConfig = new DBConfig(); //自定義的一個界面,便於輸入DB的信息 60 61 dbConfig.ShowDialog(); //安裝過程中顯示自定義的數據DB安裝信息的節目 62 63 64 65 if (this.Context.Parameters.ContainsKey("dbsource")) //用自定義的界面輸入的信息賦值給Context.Parameter,它主要負責記錄install和uninstall過程中的參數 66 67 { 68 69 this.Context.Parameters["dbsource"] = DBConfig.IP; 70 71 } 72 73 else 74 75 { 76 77 this.Context.Parameters.Add("dbsource", DBConfig.IP); 78 79 } 80 81 if (this.Context.Parameters.ContainsKey("user")) //用自定義的界面輸入的信息賦值給Context.Parameter,它主要負責記錄install和uninstall過程中的參數 82 83 { 84 85 this.Context.Parameters["user"] = DBConfig.DBUser; 86 87 } 88 89 else 90 91 { 92 93 this.Context.Parameters.Add("user", DBConfig.DBUser); 94 95 } 96 97 if (this.Context.Parameters.ContainsKey("pwd")) //用自定義的界面輸入的信息賦值給Context.Parameter,它主要負責記錄install和uninstall過程中的參數 98 99 { 100 101 this.Context.Parameters["pwd"] = DBConfig.DBPwd; 102 103 } 104 105 else 106 107 { 108 109 this.Context.Parameters.Add("pwd", DBConfig.DBPwd); 110 111 } 112 113 string dbname = "XXX"; // 數據庫的名稱 114 115 try 116 117 { 118 119 ExecuteSql("master", string.Format("DROP DATABASE [{0}]", dbname)); 120 121 } 122 123 catch 124 125 { 126 127 MessageBox.Show(string.Format("Can not delete [{0}] database. Please delete it by your self."), dbname); 128 129 } 130 131 } 132 133 } 134 135 catch (Exception ex) 136 137 { 138 139 MessageBox.Show("Can not delete some databases, please delete them manually."); 140 141 } 142 143 } 144 145 146 147 public override void Install(System.Collections.IDictionary stateSaver) 148 149 { 150 151 base.Install(stateSaver); 152 153 154 155 if (MessageBox.Show("Do you want to install databases?", "Confirm", MessageBoxButtons.YesNo) 156 157 == DialogResult.Yes) 158 159 { 160 161 DBConfig dbConfig = new DBConfig(); 162 163 dbConfig.ShowDialog(); 164 165 if (this.Context.Parameters.ContainsKey("dbsource")) 166 167 { 168 169 this.Context.Parameters["dbsource"] = DBConfig.IP; 170 171 } 172 173 else 174 175 { 176 177 this.Context.Parameters.Add("dbsource", DBConfig.IP); 178 179 } 180 181 if (this.Context.Parameters.ContainsKey("user")) 182 183 { 184 185 this.Context.Parameters["user"] = DBConfig.DBUser; 186 187 } 188 189 else 190 191 { 192 193 this.Context.Parameters.Add("user", DBConfig.DBUser); 194 195 } 196 197 if (this.Context.Parameters.ContainsKey("pwd")) 198 199 { 200 201 this.Context.Parameters["pwd"] = DBConfig.DBPwd; 202 203 } 204 205 else 206 207 { 208 209 this.Context.Parameters.Add("pwd", DBConfig.DBPwd); 210 211 } 212 213 string dbname = "XXX"; // 數據庫的名稱 214 215 ExecuteSql("master", string.Format("CREATE DATABASE[{0}]", dbname)); //創建一個數據庫 216 217 string sql = LoadSqlFromAssembly("SPRC.DB.sql"); //加載這個sql腳本 218 219 ExecuteSql(dbname, sql); //運行生成數據的sql腳本. 220 221 } 222 223 } 224
上面描述了自定義安裝的初步過程.
Read Sql and Execute Sql
1 2 3private string LoadSqlFromAssembly(string Name) 4 5 { 6 7 //得到當前程序集對象 8 9 Assembly Asm = Assembly.GetExecutingAssembly(); 10 11 //創建sql腳本的流對象 12 13 Stream strm = Asm.GetManifestResourceStream(Asm.GetName().Name + "." + Name); 14 15 //讀sql流對象 16 17 StreamReader reader = new StreamReader(strm); 18 19 return reader.ReadToEnd(); 20 21 } 22 23 24 25 private void ExecuteSql(string DatabaseName, string Sql) 26 27 { 28 29 //創建一個數據庫連接對象 30 31 this.conn = new SqlConnection(); 32 33 this.conn.ConnectionString = "user id=" + this.Context.Parameters["user"] 34 35 + ";data source=" + this.Context.Parameters["dbsource"] 36 37 + ";initial catalog=master;password=" + this.Context.Parameters["pwd"] + ";"; 38 39 //創建一個sql command對象,去運行sql腳本的內容 40 41 SqlCommand command = new SqlCommand(Sql, conn); 42 43 //open數據庫的連接 44 45 command.Connection.Open(); 46 47 //因為調用這個方法前,在install的方法裡面command是運行在master的庫上面的,所以需要change到當前數據庫中. 48 49 command.Connection.ChangeDatabase(DatabaseName); 50 51 try 52 53 { 54 55 //執行sql腳本,生成數據表和初始數據. 56 57 command.ExecuteNonQuery(); 58 59 } 60 61 finally 62 63 { 64 65 //Finally, blocks are a great way to ensure that the connection 66 67 //is always closed. 68 69 command.Connection.Close(); 70 71 } 72 73 74 75 } 76
下面描述下LoadSqlFromAssembly 和 ExecuteSql兩個方法:
自此在上面DBInstall的Project已經全部實現完畢.還需要在安裝部署中添加這個DBInstall.
創建一個Setup Project(Fileà NewàProjectàOther Project Typeà Setup and DeploymentàSetup Project,然後再剛創建號的
Setup project點擊右鍵, 點擊"添加", 選擇Project Output,在Project 選擇剛已經完成的DBInstall, 然後點擊 Primary output.
然後點擊"確定".
然後再在Setup Project上面點擊右鍵, 點擊"View"à"Custom Actions",會彈出一個窗口
然後在窗口中依次在Install, Rollback, Uninstall 三個文件夾上面創建 一個Action.
方法如下:
在文件夾上面點擊右鍵,然後點擊"Add Custom Action", 再彈出窗口裡面選擇Application Folder.
選擇剛才創建的一個DBInstall的Primary Output .
然後點擊"確定".
注意一定要在Install, Rollback, Uninstall 都添加 "Primary output from DBInstall(Active)".
只有這樣,我們在DBInstall中override的 Rollback, Uninstall才會有意義.
然後編譯setup project, 得到安裝文件,雙擊安裝.
PS: 有時候大家生成的腳本在sql裡面執行的正常, 但是在安裝過程中會出現 "Create 附近有錯誤"類似的錯誤,
請大家去掉sql文件裡面的"GO". 就可以一切正常了.
如果大家有更好的辦法, 請多多指教! 謝謝!