13/11/2013

Bài 05: Làm việc với Disconnected Data – DataSet và SqlDataAdapter

  • DataSet chứa nhiều bảng và có thể lưu trong bộ nhớ để tái sử dụng. SqlDataAdapter cho phép bạn đổ dữ liệu vào một DataSet và cập nhật thay đổi vào Database. Việc mở và đóng SqlConnection do SqlDataAdapter tự động làm việc đó. Một SqlCommandBuilder tạo ra các câu lệnh insert, update, delete dựa trên câu select của SqlDataAdapter
  • Mục tiêu bài học:
     - Tìm hiểu về DataSet
     - Tìm hiểu đối tượng SqlDataAdapter để truy xuất và cập nhật dữ liệu
     - Sự cần thiết khi dữ liệu bị ngắt kết nối
    Giới thiệu
    Ở bài 03, tôi đã giới thiệu về cách sử dụng đối tượng SqlCommand và trong bài 04 tôi đã giới thiệu về đối tượng SqlDataReader để làm việc với dữ liệu. Ở bài 05 này, tôi sẽ trình bày tiếp vấn đề liên quan đến SqlConnection và SqlDataReader bằng cách sử dụng DataSet và đối tượng SqlDataAdapter nhằm thực hiện những vấn đề liên quan đến cơ sở dữ liệu như:
    - Mở kết nối – Open connection
    - Lấy dữ liệu vào DataSet – Retrieve into DataSet
    - Đóng kết nối – Close connection
    và thực hiện các hành động sau khi cập nhật nguồn dữ liệu với thay đổi trong DataSet:
    - Mở kết nối – Open connection
    - Ghi các thay đổi từ DataSet đến nguồn dữ liệu – Write change from DataSet to data source
    - Đóng kết nối – Close connection


    Giữa hai thao tác Fill() và Update(), các kết nối nguồn được đóng và bạn có thể tự do đọc và ghi dữ liệu. Đây là những cơ chế làm việc với dữ liệu khi bị ngắt kết nối - disconnected. Vì các ứng dụng giữ cho các kết nối luôn sẵn sàng và trở nên dễ phát triển hơn.


    Một vài kịch bản minh hoạ tại sao bạn muốn làm việc với disconnected: những người làm việc không cần kết nối mạng và làm cho các trang website có khả năng mở rộng hơn. Hãy xem xét những người bán hàng, khi họ cần dữ liệu đó trong khi họ đang đi du lịch hay đi công tác. Vào đầu ngày, họ cần phải đồng bộ với dữ liệu chính để có thông tin mới nhất. Trong ngày, họ sẽ làm các thao tác thay đổi, thêm mới khách hàng, cập nhật các đơn đặt hàng mới. Điều này không quan trọng, bởi vì họ có một cơ sở dữ liệu khách hàng mà người khác không thể thay đổi. Vào cuối ngày, người bán hàng sẽ kết nối vào mạng và cập nhật các thay đổi cho việc xử lý tiến trình vào ban đêm.


    Một kịch bản khác là làm cho một trang website có khả năng mở rộng. Với một SqlDataReader, chúng ta phải quay trở lại để lấy dữ liệu mỗi khi cần hiển thị. Điều này đòi hỏi sẽ phát sinh một kết nối mới cho mỗi lần nạp (load) trang web, sẽ làm ảnh hưởng đến hiệu suất khi số lượng người truy cập tăng. Để giải quyết việc này, bạn cần dùng DataSet – vì nó được cập nhật một lần và được lưu trữ trong bộ nhớ cache. Tất cả các yêu cầu nạp lại trang web chỉ cần kiểm tra cache và nạp dữ liệu nếu không tồn tại, lấy dữ liệu và hiển thị. Điều này hạn chế việc thường xuyên kết nối cơ sở dữ liệu, giúp cho hiệu quả ứng dụng cao hơn.


    Ngoại lệ đối với kịch bản trên bao gồm các tình huống phải cập nhật dữ liệu. Sau đó bạn phải quyết định giải quyết vấn đề cho ứng dụng, bạn nên dựa trên bản chất của dữ liệu. Sử dụng disconnected khi thông tin chủ yếu là đọc, nhưng có thể thay thế bằng cách dùng đối tượng SqlCommand khi yêu cầu của ứng dụng phức tạp hơn. Ngoài ra, nếu số lượng dữ liệu quá lớn thì việc lưu trong bộ nhớ cache là không thực tế nên bạn cần sử dụng SqlDataReader cho dữ liệu chỉ đọc.
    Tạo đối tượng DataSet
    DataSet dsExample = new DataSet();
    Tạo một SqlDataAdapter


    SqlDataAdapter nắm giữ câu lệnh SQL và đối tượng kết nối cho việc đọc và ghi dữ liệu. Vì thế bạn cần khởi tạo nó với câu lệnh SQL và đối tượng kết nối
    SqlDataAdapter daExample = new SqlDataAdapter("SELECT * FROM Example", sqlConn);


    Đoạn mã trên xác định dữ liệu sẽ đọc vào DataSet với việc tạo một đối tượng SqlDataAdapter. Đối tượng connection, conn phải được khởi tạo từ trước, nhưng không được mở. Đó là công việc của SqlDataAdapter để mở và đóng kết nối khi phương thức Fill() và Update() được triệu gọi.


    Như đã nêu ở trên, SqlDataAdapter chứa tất cả câu lệnh cần thiết để tương tác với nguồn dữ liệu. Các mã lệnh trên xác định câu lệnh select, nhưng không insert, update, delete. Chúng sẽ được thêm vào SqlDataAdapter sau khi nó được khởi tạo.


    Có 2 cách để thêm các lệnh: insert, update, deleter thông qua việc sử dụng SqlDataAdapter hoặc SqlCommandBuilder.
    SqlCommandBuilder cmdBldr = new SqlCommandBuilder(daExample);


    Chú ý trong đoạn mã trên SqlCommandBuilder được thêm vào một tham số constructor của SqlDataAdapter. Điều này giúp cho SqlCommandBuilder biết đối tượng SqlDataAdapter nào để thêm vào. SqlCommandBuilder sẽ đọc câu lệnh SQL từ đó suy ra các lệnh insert, update, delete, và gán các lệnh vào các thuộc tính insert, update, delete của SqlDataAdapter tương ứng.


    Như bài học trước thì SqlCommandBuilder có những hạn chế. Nó hoạt động khi bạn thực thi vấn đề đơn giản trên một bảng duy nhất. Tuy nhiên khi bạn cần thực thi dữ liệu với nhiều bảng được lưu trữ trong một thủ tục store procedure thì nó sẽ không làm việc.
    Nạp dữ liệu vào DataSet


    Một khi bạn có một DataSet và SqlDataAdapter thì bạn chỉ cần đổ dữ liệu vào DataSet với phương thức Fill() của SqlDataAdapter.


    daExample.Fill(dsExample, tableName);


    Lưu ý, nếu bạn dùng một table để nạp dữ liệu thì tham số trong phương thức Fill() có thể đặt trùng tên với Table trong Database, nhưng nếu có từ 2 table trở lên (dùng join trong Database) thì tên của tham số này hoàn toàn khác với tên Table trong Database.
    Sử dụng DataSet


    DataSet được ứng dụng trên cả 2 hình thức Window và ASP.NET bằng cách dùng lưới GridView.


    dgExample.DataSource=dsExample;


    dgExample.DataMember=tableName;
    Cập nhật thay đổi


    Sau khi thay đổi được thực hiện trên dữ liệu bạn muốn cập nhật lại sự thay đổi này trong database, bạn chỉ cần dùng phương thức Update() của SqlDataAdapter để làm việc đó


    daExample.Update(dsExample,tableName);


    Phương thức Update() được gọi trên thể hiện của SqlDataAdapter mà ban đầu là DataSet.
    Demo cho ứng dụng:
    namespace ADO.NET
    {
        class DisconnectedDataform : Form
        {
            private SqlConnection conn;
            private SqlDataAdapter daExample;
            private DataSet dsExample;
            private DataGrid dgExample;
            private const string tableName = "Example";
            public DisconnectedDataform()
            {
                //Do du lieu
                InitData();
                //Thiet lap luoi DataGrid
                dgExample = new DataGrid();
                dgExample.Location = new Point(5, 5);
                dgExample.Size = new Size(this.ClientRectangle.Size.Width - 10, this.ClientRectangle.Size.Height - 50);
                dgExample.DataSource = dsExample;
                dgExample.DataMember = tableName;
                //Tao nut Update
                Button btnUpdate = new Button();
                btnUpdate.Text = "Update";
                btnUpdate.Location = new Point(this.ClientRectangle.Width / 2 - btnUpdate.Width / 2, this.ClientRectangle.Height - (btnUpdate.Height + 10));
                btnUpdate.Click += new EventHandler(btnUpdateClicked);
                Controls.AddRange(new Control[] { dgExample, btnUpdate });
            }
            private void InitData()
            {
                conn = new SqlConnection("Data Source=ifsoft;user id=sa;pwd=123;database=ADO.NET");
                dsExample = new DataSet();
                daExample = new SqlDataAdapter("SELECT * FROM Example", conn);
                //Fill in insert, update, and delete commands
                SqlCommandBuilder cmdBldr = new SqlCommandBuilder(daExample);
                //Fill the dataset
                daExample.Fill(dsExample, tableName);
            }
            public void btnUpdateClicked(object sender, EventArgs e)
            {
                daExample.Update(dsExample, tableName);
            }
            static void Main(string[] args)
            {
                Application.Run(new DisconnectedDataform());
            } 
        }
    }

    Tóm lại


    DataSet chứa nhiều bảng và có thể lưu trong bộ nhớ để tái sử dụng. SqlDataAdapter cho phép bạn đổ dữ liệu vào một DataSet và cập nhật thay đổi vào Database. Việc mở và đóng SqlConnection do SqlDataAdapter tự động làm việc đó. Một SqlCommandBuilder tạo ra các câu lệnh insert, update, delete dựa trên câu select của SqlDataAdapter. Dùng phương thức Fill() của SqlDataAdapter để đổ dữ liệu vào DataSet. Gọi phương thức Update() của SqlDataAdapter để cập nhật thay đổi vào lại database.

    Chúc các bạn học tập tốt! 
  • Tham khảo: http://truongminhtuan.info/Lesson/details?LessonId=18

No comments:

Post a Comment