C# Cơ bản .NET Core §1 Cài đặt, chương trình C# đầu tiên §2 Biến, kiểu dữ liệu và nhập/xuất §3 Toán tử số học và gán §4 So sánh, logic và lệnh if, switch §5 Vòng lặp for, while §6 Phương thức - Method §7 Phương thức - Delegate §8 Lớp - Class §9 Namespace §10 Partial, Nested §11 Kiểu giá trị, tham chiếu §12 Kiểu vô danh và dynamic §13 Biểu thức lambda §14 Event §15 Hàm hủy - Quá tải toán tử - thành viên tĩnh - indexer §16 null và nullable §17 Mảng §18 Chuỗi ký tự §19 Tính kế thừa §20 Phương thức khởi tạo §21 Tính đa hình - abstract - interface §22 Struct và Enum §23 Ngoại lệ Exeption §24 IDisposable - using §25 File cơ bản §26 FileStream §27 Generic §28 Collection - List §29 SortedList §30 Queue / Stack §31 Linkedlist §32 Dictionary - HashSet §33 Phương thức mở rộng §34 ObservableCollection §35 LINQ §36 (Multithreading) async - bất đồng bộ §37 Type §38 Attribute Annotation §39 DI Dependency Injection §40 (Multithreading) Parallel §41 Thư viện lớp §42 (Networking) HttpClient §43 (Networking) HttpMessageHandler §44 (Networking) HttpListener §45 (Networking) Tcp TcpListenerr/TcpClient §46 (ADO.NET) SqlConnection §47 (ADO.NET) SqlCommand §48 (EF Core) Tổng quan §49 (EF Core) Tạo Model §50 (EF Core) Fluent API §51 (EF Core) Query §52 (EF Core) Scaffold §53 (EF Core) Migration §54 (ASP.NET CORE) Hello World! §55 (ASP.NET CORE) Middleware §56 (ASP.NET CORE) Map - Request - Response §57 (ASP.NET CORE) IServiceCollection - MapWhen §58 (ASP.NET CORE) Session - ISession §59 (ASP.NET CORE) Configuration §60 (ASP.NET CORE) Gửi Mail §61 (ASP.NET RAZOR) Khởi tạo và Route §62 (ASP.NET RAZOR) Cú pháp Razor §63 (ASP.NET RAZOR) Layout trong ASP.NET Core §64 (ASP.NET RAZOR) Partial §65 (ASP.NET RAZOR) ViewComponent §66 (ASP.NET RAZOR) TagHelper §67 (ASP.NET RAZOR) PageModel §68 (ASP.NET RAZOR) Model Binding §69 (ASP.NET RAZOR) HTML Form, Validation §70 (ASP.NET RAZOR) Upload File §71 (ASP.NET RAZOR) HtmlHelper §72 (ASP.NET RAZOR) Entity Framework §73 (ASP.NET RAZOR) Paging §74 (ASP.NET RAZOR) Identity (1) - Register, Login, Logout §75 (ASP.NET RAZOR) Identity (2) Lockout, Reset Password §76 (ASP.NET RAZOR) Identity (3) Google Login §77 (ASP.NET RAZOR) Identity (4) Facebook Login §78 (ASP.NET RAZOR) Identity (5) profile, password, email ... §79 (ASP.NET RAZOR) Identity (6) Role §80 (ASP.NET RAZOR) Identity (7) Role-based Authorization §81 (ASP.NET RAZOR) Identity (8) RoleClaim §82 (ASP.NET RAZOR) Identity (9) Authorization Handler §83 (ASP.NET RAZOR) IAuthorizationService §84 (ASP.NET MVC) Controller - View §85 (ASP.NET MVC) Route §86 (ASP.NET MVC) EF, Identity §87 (ASP.NET MVC) Binding, Validation §88 (ASP.NET MVC) Xây dựng Website(1)
Lập trình C# (C Sharp)

Giới thiệu về ADO.NET

ADO.NET (ActiveX Data Object) là tập hợp các thư viện lớp qua đó cho phép ứng dụng tương tác (lấy về, cập nhật, xóa) với các nguồn dữ liệu (Như SQLServer, XML, MySQL, Oracle Database ...).

Kiến trúc để truy cập dữ liệu với ADO.NET được phân ra nhiều phần rời rạc, mỗi phần có thể sử dụng độc lập hay đồng thời nhiều thành phần được sử dụng. Cơ bản thì nó phân chia ra hai khu vực như hình dưới:

Kiến trúc ADO.NET
  • Phần thứ nhất gọi là Data Provider: là các thư viện lớp cung cấp chức năng tạo kết nối đến nguồn dữ liệu, thi hành các lệnh trên nguồn dữ liệu đó inset, update, delete, read.

    SQL Server: Loại Data Provider mặc định trong .NET CoreSqlClient ở namespace System.Data.SqlClient cung cấp khả năng kết nối đến SQL Server
    MySQL: Nếu muốn có loại Data Provider truy cập đến MySQL thì cài đặt package MySql.Data, sẽ có Data Provider MySql.Data.MySqlClient

    SQLite thì cài đặt Data Provider Microsoft.Data.SQLite

  • Phần thứ 2 gọi là DataSet là các thư viện lớp (độc lập với Data Provider) tạo ra các đối tượng để quản lý dữ liệu không phụ thuộc ngồn dữ liệu đến từ đâu, đã ở trong ứng dụng (local) hay từ nguồn XML.
    DataSet thường gồm nhiều DataTable, trong DataTable lại gồm DataColumn, các dàng buộc, các khóa chính ... Vậy DataSet là sự trừu tượng hóa một CSDL thực.

Trước tiên tìm hiểu sử dụng Data Provider với trường hợp cụ thể là SqlClient để truy cập đến CSDL MS SQL Server. Hãy gõ lệnh sau để thêm package SqlClient vào dự án:

dotnet add package System.Data.SqlClient

Sau đó trong code sử dụng thêm namespace:

using System.Data;
using System.Data.SqlClient;

Chuẩn bị SQL Server với dữ liệu mẫu

Do thực hành sử dụng SqlClient kết nối SQL Server, nên nếu chưa có hệ quản trị CSDL này thì có thể tạo một SQL Server với dữ liệu mẫu - chạy trong một Container Docker, hãy làm theo hướng dẫn phần MSSQL Container, nếu đã có SQL Server - bạn có thể phục hồi dữ liệu mẫu từ file bak xtlab.bak vào CSDL xtlab để thực hành.

Hoặc bạn có thể tải về docker-compose.yml và dữ liệu mẫu tại SQLDocker, sau đó giải nén, từ dòng lệnh vào thư mục MSSQL rồi chạy lệnh:

docker-compose up -d
docker exec sqlserver-xtlab /var/opt/mssql/backup/restore.sh

Bằng cách như vậy bạn sẽ có một SQL Server với dữ liệu mẫu có tên xtlab có cấu trục như tại Công cụ SQL Online , lắng nghe ở cổng 1433, tài khoản sa với password là Password123

Tạo kết nối với SqlConnection

SqlConnection (System.Data.SqlClient.SqlConnection) là lớp biểu diễn sự kết nối tới SQL Server. Sử sử dụng SqlConnection thực hiện như sau:

  • Tạo đối tượng SqlConnection từ một chuỗi kết nối tới SQL Server
  • Mở kết nối với phương thức Open()
  • Thực hiện các truy vấn bằng cách sử dụng các lớp như SqlCommand, SqlDataAdapter, SqlDataReader ...
  • Không còn sử dụng đến kết nối nữa thì cần đóng lại bằng phương thức Close

Ví dụ, có SQL Server ở địa chỉ localhost (hoặc 127.0.0.1), cổng kết nổi 1433, tên tài khoản là SA, password là Password123, thì tạo và mở kết nối như sau:

string sqlconnectStr     = "Data Source=localhost,1433;Initial Catalog=xtlab;User ID=SA;Password=Password123";
SqlConnection connection = new SqlConnection(sqlconnectStr);

connection.Open();                      //  Mở kết nối - hoặc  connection.OpenAsync(); nếu dùng async
/.. thực hiện cá tác  vụ truy vấn CSDL
connection.Close();                     // Đóng kết nối

Tạo chuỗi kết nối với SQL Server

Chuỗi kết nối (connection string) là tham số để khởi tạo ra đối tượng SqlConnection, chuỗi này chứa các thông tin cơ bản để thực hiện kết nối đến một SQL Server, các thông tin được chứa theo cặp key=value; ví dụ chuỗi "key 1=value1;key 2=value2", dưới dây tham khảo một số key

KEY Mô tả
Connect Timeout Số giây cố gắng kết nối trước khi phát sinh lỗi (mặc định 15s)
Timeout
Connection Timeout
Data Source Key này dùng để gán địa chỉ mạng (tên máy hoặc IP hoặc domain) của SQL Server, hoặc là tên của hiện hành đang chạy của SQL Server. Nếu muốn gán cả cổng thì sẽ thêm vào phía sau địa chỉ này ,port
Server
Address
Addr
Initial Catalog Tên của Database
Database
Password Password để kết nối
PWD
User ID Tài khoản (account) dùng để đăng nhập
UID

Tạo chuỗi kết nối cơ bản

Chuỗi có dạng như sau:

Server=ServerAddress;Database=DataBaseName;User Id=Username;Password=myPassword;

Hoặc

Data Source=ServerAddress;Database=DataBaseName;User Id=Username;Password=myPassword;

Ví dụ

SQL Server ở máy có địa chỉ IP 192.168.1.10, có CSDL tên exampledb, cho phép kết nối với User/Password là testuser/testpass, thì tạo ra chuỗi kết nối và đối tượng SqlConnection như sau:

String connectionString = "Server=192.168.1.10;Database=exampledb;User Id=testuser;Password=testpass;";
SqlConnection sqlConnection = new SqlConnection(connectionString);
sqlConnection.Open();   //Mở kết nối
//...Code truy vấn, cập nhật dữ dữ liệu ở đây
sqlConnection.Close();  //Đóng kết nối sau khi sử dụng

Nếu sử dụng using thì kết nối sẽ tự động đóng lại ở cuối khối using, nên không cần phải gọi Close

String connectionString = "Server=192.168.1.10;Database=exampledb;User Id=testuser;Password=testpass;";
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
    sqlConnection.Open();//Mở kết nối
    //...Code truy vấn, cập nhật dữ dữ liệu ở đây
}

SqlConnectionStringBuilder

SqlConnectionStringBuilder giúp tạo ra chuỗi kết nối, bằng cách thiết lập từng loại key ở trên, sau đó nó phát sinh chuỗi kết nối giúp bạn. Ví dụ:

SqlConnectionStringBuilder stringBuilder = new SqlConnectionStringBuilder();
stringBuilder["Server"]     = "127.0.0.1,1433";
stringBuilder["Database"]   = "xtlab";
stringBuilder["User Id"]    = "SA";
stringBuilder["Password"]   = "Password123";

string sqlConnectStr        = stringBuilder.ToString();

using(SqlConnection connection = new SqlConnection(sqlConnectStr))
{
    connection.Open();
    // Thực hiện  các tác vụ
}

Thông tin kết nối SqlConnection

Ở phần trên đã biết tạo ra một chuỗi kết nối, từ đó sinh ra đối tượng SqlConnection, đối tượng này được sử dụng bởi các lớp khác nhau như SqlCommand, SqlDataAdapter ... để thực hiện các truy vấn đến dữ liệu. Những đối tượng này sẽ tìm hiều ở phần sau, ở đây nói thêm một chút về SqlConnection

Một số phương thức, thuộc tính SqlConnection

State Kiểu ConnectionState trạng thái kết nối:
  • ConnectionState.Closed kết nối đã đóng
  • ConnectionState.Connecting đang kết nối
  • ConnectionState.Executing đang thi hành lệnh nào đó
  • ConnectionState.Fetching đang nhận dữ liệu về
  • ConnectionState.Open kết nối đang mở

Để kiểm tra cần thực hiện phép toán bitwise bằng phương thức FlagsAttribute, ví dụ:

if ((connection.State.HasFlag(ConnectionState.Open))
    && (connection.State.HasFlag(ConnectionState.Fetching)))
    {
        Console.WriteLine("Kết nối mở và đang nhận dữ liệu");
    }
Database Trả về tên Database - sau khi kết nối mở
StatisticsEnabled Mặc định là false, nếu thiết lập bằng true thì nó cho phép thu thập thông tin về kết nối. Để lấy thông tin thù thập được dùng phương thức RetrieveStatistics()
Open() Mở kết nối, sử dụng OpenAsync() nếu dùng kỹ thuật async
Close() Đóng kết nối
CreateCommand() Tạo đối tượng SqlCommand để thực hiện các lệnh SQL
RetrieveStatistics() Lấy thông tin thống kê (trả về IDictionary)
StateChange Event - phát sinh khi thay đổi trạng thái kết nối, muốn bắt sự kiện gán nó bằng delegate dạng
(object sender, StateChangeEventArgs e) => { /.. }

Ví dụ: Ví dụ sau có tạo ra một chuỗi kết nối tới SQL Server ở địa chỉ 127.0.0.1, sau đó bắt thông tin cho biết mỗi khi trạng thái kết nối thay đổi (open, close), có thực hiện một câu truy vấn SQL lấy dữ liệu về, cuối cùng là cho biết các thông tin thông kế đã thực hiện trên kết nối

using System;
using System.Data;
using System.Data.SqlClient;

namespace ADO_01_SqlConnection
{
  public class Exam1 {
    public static void Test () {

      // TẠO CHUỖI KẾT NỐI bằng SqlConnectionStringBuilder
      SqlConnectionStringBuilder stringBuilder = new SqlConnectionStringBuilder ();
      stringBuilder["Server"] = "127.0.0.1,1433";
      stringBuilder["Database"] = "xtlab";
      stringBuilder["User Id"] = "SA";
      stringBuilder["Password"] = "Password123";
      String sqlConnectionString = stringBuilder.ToString ();

      SqlConnection connection = new SqlConnection (sqlConnectionString);
      // kích hoạt chế độ thu thập thông tin thống kê khi truy vấn
      connection.StatisticsEnabled = true;

      Console.WriteLine ($"{"ConnectionString ", 17} : {stringBuilder}");
      Console.WriteLine ($"{"DataSource ", 17} : {connection.DataSource}");

      // Bắt sự kiện trạng thái kết nối thay đổi
      connection.StateChange += (object sender, StateChangeEventArgs e) => {
        Console.WriteLine ($"Kết nối thay đổi: {e.CurrentState}, trạng thái trước: " + $"{e.OriginalState}");
      };

      // mở kết nối
      connection.Open ();

      // Dùng SqlCommand thi hành SQL  - sẽ  tìm hiểu sau
      using (SqlCommand command = connection.CreateCommand ()) {

        // Câu truy vấn SQL
        command.CommandText = "select top(5) * from Sanpham";
        var reader = command.ExecuteReader ();
        // Đọc kết quả truy vấn
        Console.WriteLine ("\r\nCÁC SẢN PHẨM:");
        Console.WriteLine ($"{"SanphamID ", 10} {"TenSanpham "}");
        while (reader.Read ()) {
          Console.WriteLine ($"{reader["SanphamID"], 10} {reader["TenSanpham"]}");
        }
      }



      // Lấy thống kê và in số liệu thống kê
      Console.WriteLine("Thông tin thống kê các tương tác đã thực hiện trên kết nôis");
      var dicStatics = connection.RetrieveStatistics ();
      foreach (var key in dicStatics.Keys) {
        Console.WriteLine ($"{key, 17} : {dicStatics[key]}");
      }

      // Không dùng đến kết nối thì phải đóng lại (giải phóng)
      connection.Close ();

    }
  }
}

Khi chạy trong Main

static void Main(string[] args)
{
    Exam1.Test();
}

Đọc thông tin kết nối từ file config

Bạn có thể lưu chuỗi kết nối ở một cấu hình sau đó khi chạy chương trình nó sẽ đọc vào tạo thông tin kết nối, có thể sử dụng kỹ thuật Configuration lưu thông tin kết nối ở các định dạng file như json, ini, xml ... giả sử dùng định dạng json, hãy thêm các package như hướng dẫn tại config với json

dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Options.ConfigurationExtensions
dotnet add package Microsoft.Extensions.Configuration.Json

Giả sử tạo file config có tên là appconfig.json có lưu chuỗi kết nối như sau:

{
    "csdl" :  {
        "ketnoi1"  : "Data Source=127.0.0.1,1433;Initial Catalog=xtlab;User ID=SA;Password=Password123",
        "ketnoi2"  : "Data Source=localhost,1433;Initial Catalog=xtlab;User ID=SA;Password=Password123"
    }
}

Ví dụ:

using System;
using System.Data;
using System.Data.SqlClient;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Json;
using System.IO;

namespace ADO_01_SqlConnection
{
    class Program
    {
        // Lấy chuỗi kết nối từ file config định dạng json,
        // Điểm lưu: csl:ketnoi2
        public static string GetConnectString() {
            var configBuilder = new ConfigurationBuilder()
                       .SetBasePath(Directory.GetCurrentDirectory())      // file config ở thư mục hiện tại
                       .AddJsonFile("appconfig.json");                    // nạp config định dạng JSON
            var configurationroot = configBuilder.Build();                // Tạo configurationroot
            return configurationroot["csdl:ketnoi2"];

        }

        static void Main(string[] args)
        {
            // Exam1.Test();

            String sqlConnectString = GetConnectString();
            SqlConnection connection = new SqlConnection(GetConnectString());
            connection.StatisticsEnabled = true;
            connection.FireInfoMessageEventOnUserErrors = true;

            connection.StateChange += (object  sender, StateChangeEventArgs e) => {
                    Console.WriteLine($"Trạng thái hiện tại: {e.CurrentState}, trạng thái trước: " + $"{e.OriginalState}");
            };

            // Mở kết nối
            connection.Open();

            // Thực hiện các truy vấn tại đây ...

            connection.Close();

        }
    }
}
Source Code

Mã nguồn ADO_01_SqlConnection hoặc tải về ex039

Đăng ký theo dõi ủng hộ kênh