在項目中用程序中嵌入mdf文件的方式來進行SQLServer數據庫開發非常方便,用來發布開源項目等很方便,點擊就可以運行,免部署,特別是在教學中 用起來更加方便,老師不用先將數據庫文件detach再發給學生,學生也不用將數據庫文件attach。采用項目中嵌入mdf文件的方式,老師把講課的代 碼發給學生,學生打開就可以運行。我在傳智播客.net培訓班教學中就是用的這種方式進行講解。
在ASP.net程序中只要將mdf文件放到項目的App_Data文件夾即可,在連接字符串中使用
Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\CallCenter.mdf;Integrated Security=True;User Instance=True
做連接字符串即可。
但是在WinForm程序中,如果在項目的App_Data文件夾中新建一個mdf文件,然後用
Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\CallCenter.mdf;Integrated Security=True;User Instance=True
進行連接會提示找不到CallCenter.mdf。原來WinForm程序並不會去App_Data中找mdf文件。原來在ASP.net中
DataDirectory的值是當前項目的App_Data路徑,而WinForm中的DataDirectory值則是當前項目的路徑,因此
Winform中mdf文件不用放到App_Data中,放到項目根目錄下就可以。
但是新問題隨之又來了,在WinForm中用這種方式開發的時候有時候改了項目中mdf文件中的表中的數據或者表結構,運行的時候卻發現運行時通過程序讀
取的數據或者表結構沒有變,而有時調試時Insert插入的數據在這次調試的時候竟然沒有了。經過研究發現,WinForm程序運行的時候連接的是
bin/Debug下的mdf文件,而不是項目中的mdf文件,這是和ASP.net程序行為不同的地方。每次程序發生Build行為的時候,項目中的
mdf就會覆蓋bing/Debug下的mdf文件,也就是有兩個mdf文件的存在,項目中的mdf相當於“源文件”。雖然可以通過修改文件的
“BuildToOuput”屬性來部分解決問題,但是仍然不是很完美。
有一個比較很直接的想法,就是讓程序去連接項目中的mdf文件,而不是連接bin/Debug下那個。
經過查詢資料找到了修改方法,在Program.cs文件Main函數最開始加入如下代碼:
string dataDir = AppDomain.CurrentDomain.BaseDirectory;
if (dataDir.EndsWith(@"\bin\Debug\")
|| dataDir.EndsWith(@"\bin\Release\"))
{
dataDir = System.IO.Directory.GetParent(dataDir).Parent.Parent.FullName;
AppDomain.CurrentDomain.SetData("DataDirectory", dataDir);
}
原理簡單分析:連接字符串中的DataDirectory的值就是通過AppDomain.CurrentDomain.SetData賦值過去的,如果
當前程序的目錄以"\bin\Debug\"或者"\bin\Release\"則認為它是運行在VisualStudio環境中,就取項目的目錄然後賦
值給DataDirectory這個key。既然是CurrentDomain.SetData,估計對於非默認AppDomain中的數據庫連接代碼可
能會不起作用(只是猜測,沒驗證),這就要需要創建子AppDomain的時候再去賦值了。
上面的代碼還是有一點潛在的bug的,比如正式的運行的時候exe被很杯具的放到了某個bin\Debug目錄下,就會有問題,不過想想正式生產環境運行
的時候肯定不會用這種AttachDbFilename方式,這種方式只存在於開發環境,因此也就睜一只眼閉一只眼了,呵呵。
[引用來自 www.rupeng.com/forum/thread-11988-1-1.html]