0%

【C#】程式建立LocalDB(.mdf)與刪除

之前有寫如何對Repository層做單元測試【Unit Test】針對Repository做單元測試 (一),當時是直接建立LocalDB放在專案之中,測試的時候對它執行,但因為公司導入CICD流程,這些MDF會殘留在佈署的機器上,造成資源的浪費,所以同事教了新的方法,用程式直接建立LocalDB,等到測試完畢後直接砍掉的方法。

這邊記錄一下實作方法,以利之後查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
private const string LocalDbMasterConnectionString =
@"Data Source=(LocalDB)\MSSQLLocalDB;Initial Catalog=master;Integrated Security=True";

private const string TestConnectionString =
@"Data Source=(LocalDB)\MSSQLLocalDB;Initial Catalog={0};Integrated Security=True;
MultipleActiveResultSets=True;AttachDBFilename={1}.mdf";

string DatabaseName {get;set;}
void Main()
{
this.DatabaseName = "TestCreateDB";
CreateDB();
}

/// <summary>
/// 建立DB
/// </summary>
void CreateDB()
{
//先看看有沒有相同的DB存在,如果有的話卸離並移除
this.DetachDatabase();

var fileName = this.CleanupDatabase();

using (var connection = new SqlConnection(LocalDbMasterConnectionString))
{
var commandText = new StringBuilder();
//Create DB的語法
commandText.AppendFormat(
"CREATE DATABASE {0} ON (NAME = N'{0}', FILENAME = '{1}.mdf');",
this.DatabaseName,
fileName);

connection.Open();
var cmd = connection.CreateCommand();
cmd.CommandText = commandText.ToString();
cmd.ExecuteNonQuery();
}
}

/// <summary>
/// Detaches the database.
/// </summary>
private void DetachDatabase()
{
using (var connection = new SqlConnection(LocalDbMasterConnectionString))
{
connection.Open();
var cmd = connection.CreateCommand();
cmd.CommandText = string.Format("exec sp_detach_db '{0}'", this.DatabaseName);
try
{
cmd.ExecuteNonQuery();
}
catch
{
Console.WriteLine("Could not detach");
}
}
}

/// <summary>
/// Cleanups the database.
/// </summary>
/// <returns>System.String.</returns>
private string CleanupDatabase()
{
var fileName = string.Concat(@"G:\",this.DatabaseName);
try
{
var mdfPath = string.Concat(fileName, ".mdf");
var ldfPath = string.Concat(fileName, "_log.ldf");

var mdfExists = File.Exists(mdfPath);
var ldfExists = File.Exists(ldfPath);

if (mdfExists) File.Delete(mdfPath);
if (ldfExists) File.Delete(ldfPath);
}
catch
{
Console.WriteLine("Could not delete the files (open in Visual Studio?)");
}
return fileName;
}


最後就會在你寫的位置看到產生的DB了

[![](https://2.bp.blogspot.com/-zochbU5phtw/WIWuOeDVZ4I/AAAAAAAAID0/MwBAkQ4YEyQCLFLHbWnBaUiXVbtGrIseACLcB/s1600/1.png)](https://2.bp.blogspot.com/-zochbU5phtw/WIWuOeDVZ4I/AAAAAAAAID0/MwBAkQ4YEyQCLFLHbWnBaUiXVbtGrIseACLcB/s1600/1.png)

刪除

首先要先在專案安裝Entity Framerok,並且補上以下的程式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/// <summary>
/// 使用 EntityFramework 的 Database 類別 Delete 方法,確認 LocalDB 存在後再移除.
/// </summary>
public static void DeleteLocalDb(string dbName)
{
using (var connection = new SqlConnection(
string.Format(TestConnectionString,dbName, dbName)))
{
if (Database.Exists(connection))
{
try
{
SqlConnection.ClearAllPools();
Database.Delete(connection);
}
catch (Exception)
{
using (SqlConnection masterConnection = new SqlConnection(LocalDbMasterConnectionString))
{
SqlCommand cmd = masterConnection.CreateCommand();
cmd.CommandText = string.Format(
@"ALTER DATABASE [{0}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE [{0}];", connection.Database);

masterConnection.Open();
cmd.ExecuteNonQuery();
}
}
}
}
}

接著呼叫,就可以砍掉剛剛建立出來的MDF了

1
2
3
var DatabaseName = "TestCreateDB";
DeleteLocalDb(DatabaseName);

但有一點必須特別注意,如果你今天的專案結構跟我一樣

[![](https://3.bp.blogspot.com/-x8WxDPWuFrM/WIW661-YM_I/AAAAAAAAIEQ/kV7NxAeClFw5DllZUb6QK2QuKw25ksTKwCLcB/s1600/1.png)](https://3.bp.blogspot.com/-x8WxDPWuFrM/WIW661-YM_I/AAAAAAAAIEQ/kV7NxAeClFw5DllZUb6QK2QuKw25ksTKwCLcB/s1600/1.png)

刪除DB的程式碼寫在ControlLocalDB的專案中,並且在這個專案有安裝Entity Framework,而ConsoleApplication1只是引用ControlLocalDB專案來執行,而沒有安裝Entity Framework,那這時候

Database.Exists(connection)

會永遠回傳False,所以不會去砍掉DB,而且也不會引發Exception的錯誤,不知道算不算是EF的Bug,當時找超久的(崩潰),所以還請特別注意這個地方,有用到這個方法的專案都要記得專EF

參考文章:
1.HOW TO:使用 ADO.NET 與 Visual C# .NET 程式建立 SQL Server 資料庫
2.Repository 測試使用 LocalDB - Part.2