教學課程:使用 Azure SQL Database C# 以及 ADO.NET 設計關聯式資料庫
Azure SQL Database 是 Microsoft Cloud (Azure) 中的關聯式資料庫即服務 (DBaaS)。 在本教學課程裡,您將了解如何搭配使用 Visual Studio 與 Azure 入口網站和 ADO.NET 執行下列操作:
- 使用 Azure 入口網站建立資料庫
- 使用 Azure 入口網站設定伺服器層級的 IP 防火牆規則
- 使用 ADO.NET 和 Visual Studio 連線到資料庫
- 使用 ADO.NET 建立資料表
- 使用 ADO.NET 插入、更新和刪除資料
- 使用 ADO.NET 查詢資料
提示
這款免費的 Learn 模組顯示如何開發和設定可查詢 Azure SQL Database 的 ASP.NET 應用程式 (包括建立簡易資料庫)。
必要條件
- Visual Studio 2019 或更新版本的安裝。
- 如尚未擁有 Azure 訂用帳戶,請在開始之前先建立免費帳戶。
- 如果您尚未建立 Azure SQL 資料庫,請流覽快速入門:建立單一資料庫。 尋找使用供應項目免費試用 Azure SQL 資料庫 的選項(預覽)。
登入 Azure 入口網站
登入 Azure 入口網站。
建立伺服器層級 IP 防火牆規則
SQL Database 會在伺服器層級建立 IP 防火牆。 此防火牆會防止外部應用程式和工具連線到伺服器及伺服器上的任何資料庫,除非防火牆規則允許其 IP 通過防火牆。 若要啟用對資料庫的外部連線,您必須先新增 IP 位址 (或 IP 位址範圍) 的 IP 防火牆規則新增。 依照下列步驟來建立伺服器層級的 IP 防火牆規則。
重要
SQL Database 會透過連接埠 1433 通訊。 如果您嘗試從公司網路內連線到此服務,網路防火牆可能不允許透過埠 1433 的輸出流量。 若情況如此,除非系統管理員開啟連接埠 1433,否則您無法連線至您的資料庫。
部署完成之後,請從左側功能表中選取 [SQL 資料庫],然後選取 [SQL 資料庫] 頁面上的 [yourDatabase]。 資料庫的概觀頁面隨即開啟,其中會顯示完整伺服器名稱 (例如 yourserver.database.windows.net),並提供進一步的組態選項。
請複製此完整伺服器名稱,以便從 SQL Server Management Studio 連線到伺服器和資料庫。
在 [設定] 底下,選取 [網路]。 選擇 [公用存取] 索引標籤,然後選取 [公用網路存取] 下方的 [選取的網路] 以顯示 [防火牆規則] 區段。
選取工具列上的 [新增用戶端 IP],將目前的 IP 位址新增至新的 IP 防火牆規則。 IP 防火牆規則可以針對單一 IP 位址或 IP 位址範圍開啟連接埠 1433。
選取 [儲存]。 系統便會為目前的 IP 位址建立伺服器層級 IP 防火牆規則,以便在伺服器上開啟連接埠 1433。
選取 [確定],然後關閉 [防火牆設定] 頁面。
您的 IP 位址現在可以通過 IP 防火牆。 您現在可以使用 SQL Server Management Studio 或您選擇的其他工具來連線至您的資料庫。 務必使用先前建立的伺服器管理帳戶。
重要
根據預設,已對所有 Azure 服務啟用透過 SQL Database IP 防火牆存取。 選取此頁面上的 [關閉],以停用所有 Azure 服務的存取。
C# 程式範例
本文的下一節會呈現使用 ADO.NET 將 TRANSACT-SQL (T-SQL) 陳述式傳送到 SQL Database 的 C# 程式。 C# 程式會示範下列動作:
- 使用 ADO.NET 連線至 SQL Database
- 可傳回 T-SQL 陳述式的方法
- 建立資料表
- 在資料表中填入資料
- 更新、刪除及選取資料
- 將 T-SQL 提交至資料庫
實體關聯圖 (ERD)
CREATE TABLE
陳述式包含 REFERENCES 關鍵字,可建立兩個資料表之間的「外部索引鍵」(FK) 關聯性。 如果您使用 tempdb,請使用一對前置破折號將 --REFERENCES
關鍵字註解化。
ERD 會顯示兩個資料表之間的關聯性。 tabEmployee.DepartmentCode「子」資料行中的值受限於 tabDepartment.DepartmentCode「父」資料行中的值。
注意
您可以選擇編輯 T-SQL,將前置 #
新增至資料表名稱,以將其建立為 tempdb 中的暫存資料表。 沒有測試資料庫可供使用時,這很適合用於示範。 在外部索引鍵使用期間不會強制執行任何參考,而在程式完成執行之後,暫存資料表會在連線關閉時自動刪除。
編譯和執行
C# 程式在邏輯上是一個 .cs 檔案,而實際上會分成數個程式碼區塊,讓您更容易了解每個區塊。 若要編譯及執行此程式,請執行下列步驟:
在 Visual Studio 中建立 C# 專案。 專案類型應該是「主控台」,可在 [範本]>[Visual C#]>[Windows 桌面]>[主控台應用程式 (.NET Framework)] 下找到。
在 Program.cs 檔案中,利用下列步驟取代程式碼的起始行:
確認已參照 System.Data.dll 組件。 若要確認,請展開 [方案總管] 窗格中的 [參考] 節點。
若要從 Visual Studio 建置及執行程式,請選取 [啟動] 按鈕。 報告輸出會顯示在程式視窗中,而 GUID 值會隨著測試回合有所不同。
================================= T-SQL to 2 - Create-Tables... -1 = rows affected. ================================= T-SQL to 3 - Inserts... 8 = rows affected. ================================= T-SQL to 4 - Update-Join... 2 = rows affected. ================================= T-SQL to 5 - Delete-Join... 2 = rows affected. ================================= Now, SelectEmployees (6)... 8ddeb8f5-9584-4afe-b7ef-d6bdca02bd35 , Alison , 20 , acct , Accounting 9ce11981-e674-42f7-928b-6cc004079b03 , Barbara , 17 , hres , Human Resources 315f5230-ec94-4edd-9b1c-dd45fbb61ee7 , Carol , 22 , acct , Accounting fcf4840a-8be3-43f7-a319-52304bf0f48d , Elle , 15 , NULL , NULL View the report output here, then press any key to end the program...
使用 ADO.NET 連線至 SQL Database
using System;
using System.Data.SqlClient; // System.Data.dll
//using System.Data; // For: SqlDbType , ParameterDirection
namespace csharp_db_test
{
class Program
{
static void Main(string[] args)
{
try
{
var cb = new SqlConnectionStringBuilder();
cb.DataSource = "your_server.database.windows.net";
cb.UserID = "your_user";
cb.Password = "your_password";
cb.InitialCatalog = "your_database";
using (var connection = new SqlConnection(cb.ConnectionString))
{
connection.Open();
Submit_Tsql_NonQuery(connection, "2 - Create-Tables", Build_2_Tsql_CreateTables());
Submit_Tsql_NonQuery(connection, "3 - Inserts", Build_3_Tsql_Inserts());
Submit_Tsql_NonQuery(connection, "4 - Update-Join", Build_4_Tsql_UpdateJoin(),
"@csharpParmDepartmentName", "Accounting");
Submit_Tsql_NonQuery(connection, "5 - Delete-Join", Build_5_Tsql_DeleteJoin(),
"@csharpParmDepartmentName", "Legal");
Submit_6_Tsql_SelectEmployees(connection);
}
}
catch (SqlException e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("View the report output here, then press any key to end the program...");
Console.ReadKey();
}
可傳回 T-SQL 陳述式的方法
static string Build_2_Tsql_CreateTables()
{
return @"
DROP TABLE IF EXISTS tabEmployee;
DROP TABLE IF EXISTS tabDepartment; -- Drop parent table last.
CREATE TABLE tabDepartment
(
DepartmentCode nchar(4) not null PRIMARY KEY,
DepartmentName nvarchar(128) not null
);
CREATE TABLE tabEmployee
(
EmployeeGuid uniqueIdentifier not null default NewId() PRIMARY KEY,
EmployeeName nvarchar(128) not null,
EmployeeLevel int not null,
DepartmentCode nchar(4) null
REFERENCES tabDepartment (DepartmentCode) -- (REFERENCES would be disallowed on temporary tables.)
);
";
}
static string Build_3_Tsql_Inserts()
{
return @"
-- The company has these departments.
INSERT INTO tabDepartment (DepartmentCode, DepartmentName)
VALUES
('acct', 'Accounting'),
('hres', 'Human Resources'),
('legl', 'Legal');
-- The company has these employees, each in one department.
INSERT INTO tabEmployee (EmployeeName, EmployeeLevel, DepartmentCode)
VALUES
('Alison' , 19, 'acct'),
('Barbara' , 17, 'hres'),
('Carol' , 21, 'acct'),
('Deborah' , 24, 'legl'),
('Elle' , 15, null);
";
}
static string Build_4_Tsql_UpdateJoin()
{
return @"
DECLARE @DName1 nvarchar(128) = @csharpParmDepartmentName; --'Accounting';
-- Promote everyone in one department (see @parm...).
UPDATE empl
SET
empl.EmployeeLevel += 1
FROM
tabEmployee as empl
INNER JOIN
tabDepartment as dept ON dept.DepartmentCode = empl.DepartmentCode
WHERE
dept.DepartmentName = @DName1;
";
}
static string Build_5_Tsql_DeleteJoin()
{
return @"
DECLARE @DName2 nvarchar(128);
SET @DName2 = @csharpParmDepartmentName; --'Legal';
-- Right size the Legal department.
DELETE empl
FROM
tabEmployee as empl
INNER JOIN
tabDepartment as dept ON dept.DepartmentCode = empl.DepartmentCode
WHERE
dept.DepartmentName = @DName2
-- Disband the Legal department.
DELETE tabDepartment
WHERE DepartmentName = @DName2;
";
}
static string Build_6_Tsql_SelectEmployees()
{
return @"
-- Look at all the final Employees.
SELECT
empl.EmployeeGuid,
empl.EmployeeName,
empl.EmployeeLevel,
empl.DepartmentCode,
dept.DepartmentName
FROM
tabEmployee as empl
LEFT OUTER JOIN
tabDepartment as dept ON dept.DepartmentCode = empl.DepartmentCode
ORDER BY
EmployeeName;
";
}
將 T-SQL 提交至資料庫
static void Submit_6_Tsql_SelectEmployees(SqlConnection connection)
{
Console.WriteLine();
Console.WriteLine("=================================");
Console.WriteLine("Now, SelectEmployees (6)...");
string tsql = Build_6_Tsql_SelectEmployees();
using (var command = new SqlCommand(tsql, connection))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine("{0} , {1} , {2} , {3} , {4}",
reader.GetGuid(0),
reader.GetString(1),
reader.GetInt32(2),
(reader.IsDBNull(3)) ? "NULL" : reader.GetString(3),
(reader.IsDBNull(4)) ? "NULL" : reader.GetString(4));
}
}
}
}
static void Submit_Tsql_NonQuery(
SqlConnection connection,
string tsqlPurpose,
string tsqlSourceCode,
string parameterName = null,
string parameterValue = null
)
{
Console.WriteLine();
Console.WriteLine("=================================");
Console.WriteLine("T-SQL to {0}...", tsqlPurpose);
using (var command = new SqlCommand(tsqlSourceCode, connection))
{
if (parameterName != null)
{
command.Parameters.AddWithValue( // Or, use SqlParameter class.
parameterName,
parameterValue);
}
int rowsAffected = command.ExecuteNonQuery();
Console.WriteLine(rowsAffected + " = rows affected.");
}
}
} // EndOfClass
}
提示
若要深入瞭解如何撰寫 SQL 查詢,請瀏覽 教學課程:撰寫 Transact-SQL 語句。
相關內容
後續步驟
請前進到下一個教學課程,以了解資料移轉。
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應