Làm việc với cơ sở dữ liệu – ADO.NET


Trong bài viết hôm nay, chúng ta sẽ tìm hiểu về cách thức truy cập đến dữ liệu thông qua mô hình ADO.NET. Từ đó, các bạn có thể tự mình viết một ứng dụng đơn giản có sử dụng cơ sở dữ liệu

ADO.NET là mô hình mà các ứng dụng .NET sử dụng để có thể làm việc với các hệ quản trị cơ sở dữ liệu cũng như các nguồn dữ liệu khác (gọi chung là nguồn dữ liệu – data sources). Trước khi .NET xuất hiện thì mô hình được sử dụng để kết nối là ADO (ActiveX Data Object). Với sự ra đời của .NET thì ADO.NET cũng được phát triển để có thể giúp lập trình viên viết ứng dụng làm việc với các nguồn dữ liệu dễ dàng hơn và thống nhất hơn nhờ việc sử dụng chung các kiểu dữ liệu, các mẫu thiết kế (design pattern) và các quy tắc đặt tên.

ADO.NET được thiết kế với các tính năng: kiến trúc dữ liệu không kết nối (disconnected data architecture), tích hợp với XML, và được tối ưu để kết nối với cơ sở dữ liệu (và các nguồn dữ liệu khác). Mặc khác, mô hình lập trình ADO.NET cũng khá giống ADO, do đó rút ngắn thời gian tìm hiểu cho những ai đã sử dụng qua ADO trong quá khứ.

Tham khảo thêm: http://msdn.microsoft.com/en-us/library/e80y5yhx(v=vs.80).aspx

Đó là các thông tin tổng quan chung về ADO.NET, sau đây chúng ta sẽ tìm hiểu chi tiết về ADO.NET qua một ví dụ mẫu để hiểu được cách thức làm việc của ADO.NET là như thế nào, các thành phần bên trong nó gồm có những gì và sử dụng chúng ra sao. Chúng ta sẽ viết một chương trình đơn giản dùng để quản lý danh sách, giao diện của chương trình như sau:

image

Sau khi hoàn thành ứng dụng này, chúng ta sẽ có được các kiến thức sau đây:

  • Ôn lại kiến thức về Windows Forms
  • Biết được cách tạo kết nối và truy xuất dữ liệu từ SQL Server
  • Biết được cách thực thi câu lệnh SQL từ ứng dụng
  • Hiểu cơ bản về Data Binding
  • Biết cách sử dụng DataGridView

OK, let’s get started

Trước hết, chúng ta tạo một ứng dụng Windows Forms Application bằng ngôn ngữ C# trong Visual Studio và đặt tên cho ứng dụng này là ADONET (hoặc là tên gì đó mà bạn thích)

Đổi thuộc tính Name của Form1 thành MainForm và thay đổi một số thuộc tính như sau:

  • StartPosition: CenterScreen, mục đích là để form xuất hiện giữa màn hình lúc chạy
  • Text: “Quản lý danh sách”, tiêu đề của form

Tiếp theo, chúng ta kéo control DataGridView và các Label, TextBox từ ToolBox vào trong Form cùng để có được giao diện như sau, tên của các control được đặt lại là:

  • DataGridView: gridStudent
  • Nút Thêm: btnAdd; nút Xóa: btnDelete; nút Lưu: btnSave
  • Tên: txtName; Tuổi: txtAge; Email: txtEmail và Địa chỉ: txtAddress

image 

Thông tin lưu trữ của chúng ta là sinh viên và mỗi người bao gồm các thông tin sau đây: Họ tên, Tuổi, Email, Địa chỉ. Để tạo cơ sở dữ liệu, chúng ta chọn trong cửa sổ Server Explorer chức năng Connect To Database (nếu không thấy cửa số Server Explorer thì chọn từ Menu View-> Server Explorer). Lưu ý, máy tính phải được cài đặt SQL Server trước. Mặc định khi cài Visual Studio, các bạn đã được cài SQL Server Express

image 

Hộp thoại Connect To Database xuất hiện, chúng ta sẽ thấy hộp thoại có giao diện như sau:

image

Một số thành phần trong hộp thoại:

  • Data Source: chỉ định nguồn cung cấp dữ liệu cho ứng dụng. Mặc định là SQL Server, nếu thao tác với các nguồn dữ liệu khác thì chúng ta có thể thay đổi bằng cách nhất nút Change và chọn trong danh sách các loại máy chủ cung cấp dữ liệu
  • Server Name: Thông thường, nếu bạn cài đặt SQL Server Express thì tên máy chủ sẽ là “.\SQLEXPRESS” (trong đó dấu .\ có nghĩa là máy chủ chính là máy tính đang dùng – local), còn nếu như là phiên bản SQL Server đầy đủ thì tên máy chủ thường là “.\”. Để biết cụ thể tên máy chủ của mình là gì, các bạn mở SQL Server Configuration Manager (All Program-> Microsoft SQL Server –> Configuration Tools –> SQL Server Configuration Manager). Các bạn sẽ thấy danh sách các máy chủ SQL hiện có trong máy kèm theo tên. Ví dụ trong hình sau thì máy tính hiện tại có sử dụng SQL Server Express (tên máy chủ ở trong dấu ngoặc đơn).image
  • Log on to the server: chọn kiểu chứng thực để đăng nhập vào Cơ sở dữ liệu. Nếu bạn nào đã từng học qua môn CSDL thì sẽ biết tác dụng của phần này, mục đích của nó là xác nhận tài khoản được phép truy cập vào SQL Server. Mặc định của SQL Express là Windows Authentication, còn đối với các phiên bản khác thì tùy chọn này phụ thuộc lúc bạn cài đặt SQL Server.
  • Connect to a database: nếu như các bạn đã gõ Server Name ở trên rồi thì các bạn sẽ có thể nhập vào tên database cần tạo ra trong ô “Select or enter a database name”. Nếu như muốn sử dụng một database đã có sẵn thì chúng ta nhấp vào mũi tên xổ xuống để chọn database. Phần Attach a database file cho phép các bạn tạo ra một tập tin database nằm chung với ứng dụng. Khi đó, nếu như sao chép ứng dụng qua nơi khác thì tập tin này cũng được copy theo cùng. Sau khi thực hiện xong, các bạn nhấn Test Connection để kiểm tra. Nếu như hộp thoại MessageBox hiện thông báo Test Connection Succeeded thì các bạn có thể tiếp tục thực hiện phần tiếp theo. Còn không thì các bạn cần phải kiểm tra lại các thông tin mình cung cấp có chính xác hay chưa (Server Name, Authentication, Database Name…)

    Sau khi tạo thành công database, chúng ta sẽ tạo bảng dữ liệu. Trong cửa sổ Server Explorer, các bạn chọn vào database vừa tạo, mở đến nhãn Table, nhấn chuột phải chọn Add New Table.

image

Table này sẽ có các cột như sau:

image

Trường ID của chúng ta có kiểu nguyên và là trường tự động tăng (chắc các bạn vẫn còn nhớ tạo khóa IDENTITY trong môn CSDL). Để cho trường này là tự động tăng, các bạn chọn dòng của trường này và thay đổi giá trị Identity trong cửa sổ Column Properties ngay bên dưới. Chi tiết các bạn xem hình vẽ sau:

image

Lưu lại bảng này với tên Student. Sau đó, các bạn nhập vào một vài dòng dữ liệu để test ứng dụng. Nhấp chuột phải lên tên bảng, chọn Show Table Data và thực hiện việc nhập dữ liệu. Lưu ý là chúng ta không cần phải nhập dữ liệu vào cột ID bởi vì dữ liệu cột này sẽ được tự động sinh ra

image

Như vậy là chúng ta xong phần thiết lập cơ sở dữ liệu. Công việc cần thiết bây giờ là kết nối đến cơ sở dữ liệu, lấy dữ liệu ra sử dụng. Chúng ta hoàn toàn có thể sử dụng các Wizard để thực hiện các kết nối đến CSDL, tuy nhiên, trong ứng dụng này chúng ta sẽ viết code để hiểu rõ chi tiết hoạt động của các thành phần là như thế nào.

Đoạn code sau đây được khai báo trong lớp của Form chúng ta vừa tạo (chọn Form, nhấp chuột phải chọn View Code hoặc nhấn F7)

//Tạo kết nối đến database
SqlConnection connection = new SqlConnection(@"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\Xuan Chien\Desktop\ITIC\ADONET\StudentDB.mdf;Integrated Security=True;User Instance=True");

//Data Adapter
SqlDataAdapter da;

//DataSet dùng để lưu trữ lại dữ liệu lấy từ SQL Server
DataSet ds = new DataSet();

//ID hiện tại
int studentID = -1;

//Nếu người dùng dùng chức năng thêm thì add=true
bool add = false;

Giải thích:

  • SqlConnection: dùng để chỉ rõ là chúng ta kết nối đến đâu. Để chỉ định các thông tin như Server Name, Database Name, Authentication thì ta cần phải truyền vào cho constructor của lớp SqlConnection một chuỗi kết nối (Connection String). Chi tiết về chuỗi kết nối thì các bạn xem tại: connectionstrings.com. Nói một cách tổng quát, chuỗi kết nối là cách chúng ta truyền vào thông tin cách thức kết nối đến nguồn dữ liệu. Ví dụ, xét chuỗi kết nối sau: “Data Source=.\sqlexpress;Initial Catalog=AdventureWorksLT2008;Integrated Security=True”. Trong chuỗi kết nối, chúng ta đã chỉ định rằng Server của SQL Server là .\sqlexpress, CSDL được dùng là AdventureWorksLT2008, cơ chế chứng thực là Windows Authentication.
  • DataSet: đây là đối tượng mà sẽ chứa toàn bộ dữ liệu chúng ta truy xuất được từ database. Ứng dụng của chúng ta sẽ thao tác trên dữ liệu trong DataSet này. Sử dụng DataSet cho phép chúng ta chỉ truy xuất dữ liệu từ database 1 lần duy nhất và kết nối đến Database sẽ được ngắt đi ngay sau khi truy xuất.
  • SqlDataAdapter: đối tượng của lớp này hoạt động như là một cầu nối để đưa dữ liệu từ database đổ vào DataSet. Đối tượng lớp này chịu trách nhiệm tự động quản lý đóng mở kết nối đến database.
  • studentIDadd: giải thích sau

Đoạn code quan trọng tiếp theo nằm trong hàm xử lý sự kiện Load của Form dùng để đưa dữ liệu lên Grid. Nội dung đoạn code như sau:

//Tạo Data Adapter
da = new SqlDataAdapter("Select * from Student", connection);

//Data Adapter sẽ tự động sinh ra khóa chính từ khóa chính ở Database
da.MissingSchemaAction = MissingSchemaAction.AddWithKey;

//Kết nối và đưa dữ liệu vào DataSet
da.Fill(ds, "Student");

//Hiển thị lên Data Grid View (Data Binding)
gridStudent.DataSource = ds.Tables["Student"];

Chúng ta trước khởi tạo một đối tượng SqlDataAdapter, cung cấp cho constructor câu lệnh Select để lấy dữ liệu và đối tượng chứa kết nối đến Database. Sau đó, chúng ta chỉnh giá trị của thuộc tính MissingSchemaAction sang AddWithKey để yêu cầu DataAdapter ánh xạ trường khóa chính vào trong DataSet. Nhờ việc thiết lập này mà sau này ta có thể tìm kiếm một dòng dữ liệu trên DataSet bằng cách cung cấp giá trị khóa. Đến đây thì việc kết nối đến CSDL và truy xuất vẫn chưa được thực hiện. Chỉ khi các bạn gọi phương thức Fill của DataAdapter thì lúc này dữ liệu mới được lấy từ Database và đổ vào DataSet. Tham số thứ 2 của phương thức Fill là chỉ định tên của bảng dữ liệu mà chúng ta sẽ quy định cho dữ liệu được đưa vào DataSet. Tên này không nhất thiết là phải giống như tên bảng dưới cơ sở dữ liệu mà có thể là một cái tên bất kỳ.

Dữ liệu đã được lấy ra, việc cuối cùng chỉ là hiển thị nó lên giao diện người dùng. Chúng ta sẽ chỉ định thuộc tính DataSource của gridStudentds.Tables[“Student”]. Điều này có nghĩa là sử dụng dữ liệu nằm trong một bảng có tên “Student” ở trong DataSet. Các bạn cần nhớ rằng 1 DataSet thì có thể chứa nhiều dữ liệu từ các bảng khác nhau. Việc gắn dữ liệu từ Database lên giao diện được gọi là DataBinding. Đối với các control khác như ListBox hay ComboBox thì chúng ta cũng có thể Binding dữ liệu vào thông qua thuộc tính DataSource và các thuộc tính DisplayMember, DisplayValue

Sau khi đã hoàn thành các bước ở trên thì khi chạy chương trình, chúng ta sẽ có được giao diện như sau:

image

Việc tiếp theo đó là chúng ta phải hiển thị thông tin chi tiết của dòng dữ liệu đang được chọn trong Grid vào các TextBox bên phải cửa sổ. DataGridView cung cấp cho chúng ta sự kiện RowEnter. Sự kiện này sẽ được gọi mỗi khi có một ô trên dòng nào đó được chọn (RowIndex thay đổi). Phương thức xử lý của sự kiện này là như sau:

private void gridStudent_RowEnter(object sender, DataGridViewCellEventArgs e)
{
    //Người dùng đang trong chế độ chỉnh sửa dữ liệu
    add = false;

    //Lấy ID của dòng hiện tại đang được chọn trong GridView
    studentID = Int32.Parse(gridStudent.Rows[e.RowIndex].Cells["ID"].Value.ToString());

    //Lấy ra dòng dữ liệu được chọn trong DataSet
    DataRow dr = ds.Tables["Student"].Rows.Find(studentID);

    //Hiển thị thông tin lên các TextBox
    txtName.Text = dr["Name"].ToString();
    txtAge.Text = dr["Age"].ToString();
    txtEmail.Text = dr["Email"].ToString();
    txtAddress.Text = dr["Address"].ToString();
}

Trước hết, chúng ta thiết lập giá trị cho biến add thành false. Mục đích của biến này là để cho ứng dụng của chúng ta biết là chúng ta đang thêm mới một dòng dữ liệu hay là đang chỉnh sửa dữ liệu hiện có khi nhấn nút “Lưu”. Vì khi người dùng chọn vào một dòng, thông tin dữ liệu của dòng này được hiển thị và cho phép người dùng chỉnh sửa nên biến add được thiết lập giá trị là false.

Tiếp theo đó, chúng ta lấy ra ID của dòng dữ liệu được chọn. Các bạn để ý thấy rằng khi chạy chương trình, chúng ta có một cột dữ liệu có tên là ID. Dựa vào cột ID này mà chúng ta biết được ID của dòng dữ liệu được chọn. Giá trị ID này được lưu vào biến studentID của form nhằm sử dụng cho trường hợp cập nhật dữ liệu trong sự kiện của nút “Lưu”

Đã có được ID của dòng dữ liệu, bây giờ chúng ta chỉ cần lấy ra dòng dữ liệu thực sự chứa ID này trong DataSet của chúng ta. Việc truy xuất này khá đơn giản, chỉ cần chúng ta chỉ định bảng nào trong DataSet cần lấy dữ liệu và dùng phương thức Find của tập Rows trên bảng dữ liệu đó. Các bạn có thể thắc mắc là làm sao nó biết được phải tìm kiếm trên cột nào trong bảng. Theo mặc định nó sẽ tìm kiếm trên khóa chính của bảng, đó là lý do tại sao chúng ta phải thiết lập thuộc tính MissionSchemaAction của DataAdapter. Sau khi lấy được dòng dữ liệu này rồi thì chúng ta thiết lập giá trị Text của các TextBox nhằm hiển thị dữ liệu.

Nhấn F5 để chạy chương trình, kết quả chúng ta có được là như sau:

image

Công việc cuối cùng lúc bấy giờ chính là viết sự kiện xử lý cho các button của chúng ta. Hãy lần lượt đi qua từng phương thức xử lý sự kiện click của mỗi Button để hiểu rõ chức năng và cách chúng hoạt động.

  1. Thêm

    Khi người dùng nhấn nút “Thêm”, chúng ta chỉ đơn giản là xóa nội dung Text trong những TextBox để người dùng nhập thông tin mới, đồng thời thay đổi biến add thành true (các bạn có thể dễ dàng nhận thấy add hoạt động như một biến cờ để thông báo về sự thay đổi trạng thái)

    //Xóa nội dung trong các TextBox chuẩn bị cho dữ liệu nhập
    txtName.Text = "";
    txtAge.Text = "";
    txtAddress.Text = "";
    txtEmail.Text = "";
    
    //Chuyển sang chế độ Thêm dữ liệu
    add = true;

  2. Xóa

    Khi người dùng nhấn nút “Xóa”, chúng ta trước hết kiểm tra xem thực sự có dòng nào đang được chọn trên gridStudent hay không, sau đó hiển thị một MessageBox hỏi người dùng có chắc chắn muốn xóa dữ liệu này. Nếu người dùng đồng ý thì chúng ta thực hiện xóa dòng dữ liệu tương ứng trên DataSet và cập nhật xuống database

    private void btnDelete_Click(object sender, EventArgs e)
    {
        //Chắc chắn rằng người dùng đang chọn một dòng trên grid
        if (gridStudent.SelectedCells.Count == 0)
            return;
    
        //Hiển thị thông báo xóa dữ liệu
        DialogResult result = MessageBox.Show("Bạn có thật sự muốn xóa dòng dữ liệu này?", "Thông báo", MessageBoxButtons.YesNo);
        if (result == System.Windows.Forms.DialogResult.Yes)
        {
            DataRow dr = ds.Tables["Student"].Rows.Find(studentID);
            dr.Delete();
            SqlCommandBuilder commandBuiler = new SqlCommandBuilder(da);
            da.Update(ds, "Student");
        }
    }

    Các bạn lưu ý dòng khởi tạo đối tượng SqlCommandBuilder. Nếu như chúng ta chỉ muốn hiển thị dữ liệu thì dòng này là không cần thiết, tuy nhiên nếu như chúng ta muốn cập nhật dữ liệu (Thêm, Xóa, Sửa) trên Database thì dòng khởi tạo này là cần thiết. Dòng khởi tạo này sẽ thiết lập DataAdapter của chúng ta các câu lệnh Insert, Update và Delete mặc định cho việc cập nhật dữ liệu. Sau khi đã thiết lập xong, chúng ta gọi phương thức Update của DataAdapter. Trong phương thức Update cần phải chỉ rõ là DataSet nào cập nhật và bảng nào trên DataSet được cập nhật xuống CSDL. Nếu như chúng ta không gọi phương thức Update này thì các bạn có thể thấy rằng dữ liệu hiển thị trên Grid vẫn biến mất như là đã bị xóa. Nhưng thực sự lúc đó chúng ta chỉ xóa dữ liệu đó trên DataSet, hoàn toàn tách biệt với Database (các bạn còn nhớ kiến trúc dữ liệu không kết nối của ADO.NET chứ?)

  3. Lưu

    Khi người dùng nhấn nút “Lưu” thì cần phải xét 2 trường hợp là liệu người dùng đang thêm một dòng dữ liệu mới hay là người dùng đang cập nhật một dòng dữ liệu hiện có. Tùy vào từng tình huống mà chúng ta sẽ xử lý cho dữ liệu trên DataSet tương ứng

    private void btnSave_Click(object sender, EventArgs e)
    {
        //Nếu người dùng đang chỉnh sửa dữ liệu
        if (!add)
        {
            //Lấy ra dòng dữ liệu đang được chọn trong DataSet
            DataRow dr = ds.Tables["Student"].Rows.Find(studentID);
            
            //Bắt đầu chỉnh sửa dữ liệu
            dr.BeginEdit();
    
            //Cập nhật
            dr["Name"] = txtName.Text;
            dr["Age"] = txtAge.Text;
            dr["Email"] = txtEmail.Text;
            dr["Address"] = txtAddress.Text;
    
            //Kết thúc chỉnh sửa dữ liệu
            dr.EndEdit();
        }
        else //Người dùng thêm dữ liệu mới
        {
            //Tạo ra một dòng dữ liệu mới
            DataRow dr = ds.Tables["Student"].NewRow();
    
            //Đưa thông tin vào dòng dữ liệu này
            dr["Name"] = txtName.Text;
            dr["Age"] = txtAge.Text;
            dr["Email"] = txtEmail.Text;
            dr["Address"] = txtAddress.Text;
    
            //Thêm dòng dữ liệu này vào DataSet
            ds.Tables["Student"].Rows.Add(dr);
        }
    
        //Tạo đối tượng SqlCommandBuilder để có thể cập nhật dữ liệu
        SqlCommandBuilder commandBuilder = new SqlCommandBuilder(da);
    
        //Cập nhật các thay đổi đã thực hiện trên DataSet.
        //Không có dòng này thì dữ liệu sẽ không được cập nhật trên database
        da.Update(ds, "Student");
    }

    Nếu như người dùng đang cập nhật một dòng dữ liệu đã có thì chúng ta lấy dòng dữ liệu đó ra và chỉnh sửa lại các thông tin trên dòng dữ liệu đó. Các phương thức ds.BeginEdit()ds.EndEdit() có tác dụng ngăn chặn các sự kiện khác có thể xảy ra trên dòng dữ liệu này khi gán các giá trị mới cho chúng (ví dụ như kiểm tra Lỗi, Validation, RowStateChanged….). Trường hợp người dùng thêm dữ liệu thì chúng ta sẽ tạo một DataRow mới nhờ phương thức NewRow() của bảng trong DataSet, sau đó chúng ta gán giá trị cho các trường của DataRow và cuối cùng là thêm dòng dữ liệu này vào danh sách các dòng dữ liệu đang có.

    Trong cả 2 trường hợp, chúng ta đều cần thiết phải cập nhật dữ liệu xuống database bằng phương thức Update của DataAdapter.

    Đến đây thì ứng dụng nhỏ của chúng ta đã hoàn thành. Các bạn nhấn F5 để chạy và thử nghiệm các tính năng Thêm, Xóa, Sửa của ứng dụng.

    Download chương trình Demo tại đây: ADONET

Kết luận: ADO.NET là một công nghệ nền tảng của .NET dùng trong việc truy cập vào CSDL. Các đối tượng như DataAdapter và DataSet làm việc kết hợp với nhau tạo nên kiến trúc dữ liệu không kết nối, điều này giúp tăng tốc độ làm việc với CSDL cũng như tiết kiệm tài nguyên hệ thống (không cần phải duy trì kết nối liên tục đến database). Trong các bài tiếp theo, chúng ta sẽ tìm hiểu về một số cách khác có thể giúp bạn truy xuất và cập nhật cơ sở dữ liệu như DataReader hoặc tìm hiểu về công nghệ ADO.NET Entity Model giúp cho các thao tác với CSDL trở nên dễ dàng hơn lúc trước rất nhiều. Chúc các bạn thành công!

92 thoughts on “Làm việc với cơ sở dữ liệu – ADO.NET

  1. A ơi, sao e làm bt Xóa code như trên nhưng mà khi xóa xong, rồi cho chạy lại thì cái row e đã xóa trước đó vẫn còn vậy ?

      • đây a

        private void btXoa_Click(object sender, EventArgs e)
        {
        if (dtvDanhsach.SelectedCells.Count == 0)
        return;
        string data = “Xóa chứ ?”;
        if (MessageBox.Show(data, “Thông báo”, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
        {
        DataRow dr = ds.Tables[“Student”].Rows.Find(studentId);
        ds.Tables[“Student”].Rows.Remove(dr);
        SqlCommandBuilder commandbuilder = new SqlCommandBuilder(da);
        da.Update(ds, “Student”);
        }
        }

      • A ơi cho e hỏi :
        Ở cái datagridview ấy ạ.e muốn có thêm trường cuối cùng trống để khi mình thêm dữ liệu thì nhập trực tiếp trên datagridview

  2. Cho mình hỏi,vậy làm sao ta lấy được csdl ra,để mang cái project này qua máy khác mà nó vẫn hỉu.Cảm ơn

    • Nếu dữ liệu của mình chỉ định là dùng ở Database Server (có nghĩa là máy của mình hoạt động như một máy chủ chứa CSDL thì khi đem sang máy khác chúng ta phải thực hiện Attach database đó vào trong SQL Server và phải chỉnh lại Connection String. Còn nếu như chúng ta dùng Database dạng đi kèm theo ứng dụng (trong connection string sẽ có dạng AttachDbFileName=…) thì chúng ta chỉ cần thay đổi Connection String là được. Thân

  3. anh ơi em có một cái CSDL trên sql gồm 2 cột 1 cột là MaPhong, 1 cột là Tenphong tương úng với cái mã phòng đó.Bây jo e thiết kế một cái form chứa cái combobox đó, em mún khi lựa chọn các mã phòng thi tên của phòng đó hiện ra trên label e phải viết sao anh. Em đang cần gấp anh pm sơm dùm em

    • Không biết có phải yêu cầu của em là ComboBox sẽ hiển thị mã phòng và khi chọn mã phòng đó thì sẽ hiển thị tên Phòng trên một Label khác. Em có thể load hết toàn bộ dữ liệu lên ứng dụng 1 lần duy nhất (lúc này toàn bộ dữ liệu đang ở trong DataTable của DataSet). Em sẽ Bind dữ liệu lên ComboBox như sau (giả sử tên ComboBox là cmbMaPhong):
      cmbMaPhong.DataSource = ds.Tables[“Phong”];
      cmbMaPhong.DisplayMember = “MaPhong”;
      cmbMaPhong.ValueMember = “MaPhong”; (trong trường hợp em muốn rằng hiển thị tên phòng trong ComboBox thì DisplayMember= “TenPhong”)
      Khi người dùng chọn thay đổi lựa chọn trong ComboBox thì sự kiện SelectedIndexChanged sẽ được gọi. Em sẽ viết hàm xử lý sự kiện này. Lấy giá trị mã phòng (cmbMaPhong.SelectedValue), sau đó dựa vào mã phòng này mà hiện thị tên phòng trên Label bằng cách tìm trong DataTable chứa dữ liệu Phòng.

  4. anh ơi em down một cái file pdf về mà không đoc đc tại nó có thêm cái đuôi .com ở phía trước đuôi pdf jo làm sao đọc được file đoa anh chỉ em với

  5. Cách của anh làm là thông qua combobox, còn nếu em muốn edit trực tiếp trên bảng hiện thị của datagridview thì làm như thế nào?
    Tức là khi Debug thì hiện lên bảng, khi bấm nút edit thì ta có thể sửa dữ liệu ở các Cell, đồng thời cũng add thêm 1 Row mới để ta có thể thêm dữ liệu. Sau khi nhập trực tiếp xong thì nhấp nút Save, lập tức bên cái bảng trong cơ sở dữ liệu cũng được cập nhật như ta vừa sửa trên datagridview. Mong anh hồi đáp sớm.
    Núi Ấn, Sông Trà

    • Hi. Sorry vì hôm qua anh quên reply vì có chút việc. A chưa hiểu ý của em lắm vì anh không sử dụng ComboBox nào cả, chắc là em đang nói là tại sao anh ko sử dụng chỉ DataGridView thôi mà lại dùng tới các TextBox. Em có thể chọn mũi tên bên góc trên phải của DataGridView, trong đó sẽ có các tùy chọn để em cho phép chỉnh sửa dữ liệu trực tiếp trong DataGridView đó.
      Thân,

  6. Pingback: Sử dụng GridView trong ASP.NET « My power is my mind

  7. Bạn cho mình hỏi làm sao để hiện thì sự kiện RowEnter để minh viết code vào đó. Sự kiện này năm trong file nào trogn ví dụ của bạn vậy. :(

    • Bạn chọn control cần viết sự kiện và mở cái khung Properties, sau đó chọn cái icon hình sấm sét để xem danh sách sự kiện của Control đó, tìm đến dòng có chữ RowEnter và double click vào đó để tạo phương thức xử lý sự kiện. Phương thức này nằm trong File có đuôi .cs và tên trùng với tên Form (Bạn có thể nhấn chuột phải lên form chọn View Code)

      • Bạn nói cụ thể hơn trong ví dụ của bạn thì từng bước làm thế nào để hiện ra sự kiện :
        private void gridStudent_RowEnter(object sender, DataGridViewCellEventArgs e)
        Mình mới học bạn cố gắng giúp đỡ từng bước mình mới hiểu và làm theo được.
        Xin cảm ơn nhé!

  8. NGANH(Manganh,Makhoa,Tennganh,He, TongSoTC)
    KHOANTHU(Makthu, NamHoc ,Tenkhoanthu)
    MUCTHU(Makthu,Manganh, ,Sotiendm)
    Giá trị tableMucThu( HP2004, 101,50000)
    -Mình có comboboxNganh, comboboxKhoanThu

    – Mình muốn khi chọn ngành và khoản thu thì sẽ lấy được SoTienDM = 50000

    • Không biết là bạn cần giúp đỡ chỗ nào? Bạn cần nêu rõ thắc mắc đang gặp phải thì mình sẽ trợ giúp, chứ câu hỏi chung chung thế này thì mình sẽ không biết trả lời như thế nào cho đúng.
      Thân,

  9. SqlConnection connection = new SqlConnection(@"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\Xuan Chien\Desktop\ITIC\ADONET\StudentDB.mdf;Integrated Security=True;User Instance=True");

    mÌnh có thể đổi connect string này để sang máy khác chạy luôn được không?

  10. pro wa, mình cũng đang làm project này, nhưng mình đang vướn phải vấn đề là không thể cập nhật dữ liệu được trong dataset mà nó cập nhật thẳng qua SQL luôn.
    Mình đang làm Console Appplication. Rất vui khi được các làm quen với các bạn

  11. Anh cho em hoi la, khi pushlish ung dung do thanh mot chuong trinh chay tren desktop, neu co bo sung them button search thi bat buot phai co du lieu trong datagridview moi search duoc, nhung truc tiep lam luc may con khoi dong thi search duoc, nhung khi restar lai may thi du lieu da nhap truoc do bi mat thi lam sao a?
    anh giup em doan code ma luu du lieu mai mai trong ung dung csdl ma khong bi mat khi ta restar lai may, cac rows chi bi mat khi ta nhan button delete thoi. em cam on nhiu, hihihihihihihihihih

  12. Giúp mình với nhé… File tui down về chỉ sửa chuỗi kết nối thôi.

    SqlConnection connection = new SqlConnection(@”Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\StudentDB.mdf;Integrated Security=True;User Instance=True”);

    Nó vẫn chạy và vẫn lấy đc data trong Student.mdf xuất ra gridview

    Khi mình thêm, xóa, sửa thì nó vẫn thực hiện tốt trên gridview nhưng lại không cập nhật vào database.

    Mình không biết tại mình dùng 2005 nó khác với 2008 của bạn hay sao mà nó không cập nhật được T_T.

  13. Tại sao mình chạy procedure trong sql thì cho kết quả như theo thủ tục, còn khi mình kết nối với visual c# thì kết quả lại khác nó không giống với điều kiện trong thủ tục.Ban coi giùm mình nhé:

    create procedure MyDirectory.Sale_by_Year_Category
    @CategoryID int,
    @CategoryName nvarchar(15),
    @OrderYear int
    as
    begin
    select p.ProductName,round(sum(v_o.Sale),2)’Total’ from Northwind.dbo.Categories c join Northwind.dbo.Products p on c.CategoryID=p.CategoryID join Northwind.dbo.View_Orders v_o on p.ProductID=v_o.ProductID
    where (@CategoryID is null or c.CategoryID=@CategoryID)
    and (@CategoryName is null or c.CategoryName=@CategoryName)
    and (@OrderYear is null or year(v_o.OrderDate)=@OrderYear)
    group by p.ProductName
    order by Total desc

    declare @SumMoney int
    select @SumMoney=round(SUM(v_o.Sale),2)
    from Northwind.dbo.Categories c join Northwind.dbo.Products p on c.CategoryID=p.CategoryID join Northwind.dbo.View_Orders v_o on p.ProductID=v_o.ProductID
    where (@CategoryID is null or c.CategoryID=@CategoryID)
    and (@CategoryName is null or c.CategoryName=@CategoryName)
    and (@OrderYear is null or year(v_o.OrderDate)=@OrderYear)
    return @SumMoney
    end

    Như thế này: Khi ta nhập CategoryID, và CategoryName la null thì nó sẽ lọc điều kiện theo CategoryID va OrderYear, ngược lại nếu ta nhập CategoryName, còn CategoryID la null thì nó sẽ dựa theo điều kiện CategoryName và OrderYear. Còn nếu mình nhập giá trị cả hai CategoryID & CategoryName nếu CategoryName thuộc CategoryID thì nó sẽ truy xuất, ngược lại thì null. Mình đã chạy trên SQL thì nó vẫn tốt, kết quả logic như suy luận. Nhưng khi mình chạy trong môi trường ADO thì khác nó bắt phải cả hai giá trị là CategoryID & CategoryName phải được nhập và CategoryName phải có ID là CategoryID thì truy xuất kết quả được. Nếu một trong hai null hoặc cả hai null thì truy xuất ra null. Mình nghe nói nếu như mình sử dụng điều kiện:

    (@CategoryID is null or c.CategoryID=@CategoryID)
    and (@CategoryName is null or c.CategoryName=@CategoryName)
    and (@OrderYear is null or year(v_o.OrderDate)=@OrderYear)

    thì có thể bị lỗi sniffing gì đó. Không biết đúng không???Mong mọi người giúp đỡ..Thankssss

    • Mình ít khi trả lời trên yahoo, bạn nên hỏi trên các diễn đàn như congdongcviet thì sẽ có rất nhiều người giải đáp cho bạn, hơn nữa sau này khi người khác gặp vấn đề tương tự thì họ cũng tìm được giải đáp trên diễn đàn đó luôn. Thân,

  14. em muon tim kiem ten nhan vien va ten cua don vi va khi tim thi bang nhan vien hien tren dagirdview bang nhan vien co (manv, hotennv,ngaysinh,phai,diachi,manql,madv) k etnoi voi bang donvi(madv,tendonvi,sdt,trdv)

  15. KHI LÀM NÚT XÓA MÌNH BỊ LỖI CHỖ NÀY
    SqlConnection ketnoi = new SqlConnection(“Server=.\\BAONGOC-PC; Database=QLBH1; Integrated Security=true;”);
    SqlCommand command3 = new SqlCommand(“select * from NHANVIEN”, ketnoi);
    SqlDataAdapter NV = new SqlDataAdapter(command3);
    if (dataGridView4.SelectedCells.Count == 0)

    return;
    DialogResult result = MessageBox.Show(“Bạn có thật sự muốn xóa dòng dữ liệu này?”, “Thông báo”, MessageBoxButtons.YesNo);

    if (result == System.Windows.Forms.DialogResult.Yes)

    {
    DataRow dr = ds.Tables[“NHANVIEN”].Rows.Find(MANV);//?? KHONGN BIET LOI NAY SUA SAO??????

    dr.Delete();

    SqlCommandBuilder commandBuiler = new SqlCommandBuilder(NV);

    NV.Update(ds, “NHANVIEN”);

  16. lỗi đó mình sửa được rồi nhưng bị lỗi này sau khi mình debug chương trình
    row = ds.Tables[“nhan vien”].Rows.Find(manv)
    lỗi:
    {“Object reference not set to an instance of an object.”}
    nó báo chỗ manv

  17. vẫn bị lỗi bạn ơi
    DataRow dr = ds.Tables[0].Rows.Find(manv);
    lỗi
    {“Cannot find table 0.”} mình làm theo cách bạn chỉ
    mà mình có đặt tên bảng mà trong sql mình có tạo bảnh nhân viên mà

    • Cái bảng trong SQL nó khác với cái bảng mà bạn truy vấn được. Mình mới xem lại code của bạn thì mình không thấy bạn đưa dữ liệu vào Dataset (biến ds). Bạn xem lại các phần code sử dụng SqlDataAdapter và DataSet thử xem.

  18. Bạn làm ơn cho mình hỏi, khi mình delete dữ liệu trong một bảng có liên kết khóa ngoài với bảng khác thì nó báo lỗi, và không thể xóa được. Bạn có thể chỉ cho mình cách để xóa dữ liệu ở tất cả các bảng có liên kết khóa ngoài với nó không nhỉ.
    Ví dụ: Xóa Sinh viên trong bảng SinhVien thì sẽ xóa luôn cả Sinh viên đó trong bảng LopHoc
    Cảm ơn bạn nhiều!

  19. Bạn ơi mình có vấn đề này là mình dựa trên nền code của bạn mình làm rất thành công.Nhưng bây giờ có vấn đề là cứ mỗi lần nhập dữ liệu là phải bấm lưu.Bạn có cách nào mà vẫn trên nền code đó nó tự động lưu không.Bạn làm ơn giúp mình.Mình đang cần gấp lắm.Cám ơn bạn.

    • Ở đây mình đặt đoạn code lưu trong btnClick, còn bạn thích đặt nó trong sự kiện khác vẫn được, ví dụ như sự kiện TextChanged của các textbox….

  20. Huynh oi cho de hoi de da hien thi duoc thong tin len gritview oi nhung ma toi phan hien thi cac thong tin qua cac text thi ko duoc code thi ko thay bao loi
    Huynh oi chi dum de cai phan
    ID nha
    thankss

  21. Cho mình hỏi 1 chút:”Mình đang làm về quản lý sinh viên.Nếu bây giờ dùng mã sv làm khóa chính thì nó sẽ báo lỗi.Mình đoán là do mã sv ko phải kiểu int.Không biết thế có đúng k nữa???Bạn giải thích dùm mình nhé

  22. Cho mình hỏi là:
    VĐ 1: Mình tạo sẵn 1 datagridview và có sẵn các cột như “Mã Sinh Viên”, “Họ”, “Tên”…
    và khi mình load CSDL lên thì nó chỉ load thông tin ứng với cột đó trong CSDL lên thôi nhưng không thay đổi số cột cũng như tên cột đó.. Xin cảm ơn !!!

  23. Xuân Chiến ơi, bạn có thể giải thích cho mình phần kết nối này SqlConnection connection = new SqlConnection(@"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\Xuan Chien\Desktop\ITIC\ADONET\StudentDB.mdf;Integrated Security=True;User Instance=True");
    trong đó đoạn này @"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\Xuan Chien\Desktop\ITIC\ADONET\StudentDB.mdf;Integrated Security=True;User Instance=True" mình lấy đâu ra vậy ? Thanks bạn rất nhiều !

  24. Anh ơi cho em hỏi: Từ bài của anh em muốn thêm một nút button là Tìm kiếm, giả sử là tìm kiếm theo ID, khi đánh ID vào thì thông tin sinh viên sẽ hiện lên các textbox, em làm mãi mà không được. Cám ơn anh rất nhiều

  25. anh ơi. cho em hỏi là em tạo một cái dataset, khi em coppy dữ liệu sang máy khác attach đuôi mdf trong sql server chạy rùi, nhưng trong data set của vb thì nó báo lỗi không chạy được . a gúp e mới.

  26. Anh cho em hỏi là: Trong phần hiển thị thông tin lên các textbox : txtName,txtAge,txtEmail,txtAddress em thấy là khi mình click chuột vào một dòng dữ liệu thì các dữ liệu đó đều phải có trong gridStudent thôi.Mình có cách nào mà có thể hiển thị được thông tin không có trong gridStudent không ạ ? em VD : là trong CSDL của em sẽ có thêm một Column là số điện thoại và trên MainForm sẽ có 1 textBox là số điện thoại nhưng khi select để hiển thị các column thông tin lên gridStudent em sẽ không chọn column số điện thoại. Vậy khi mình click vào một dòng trên gridStudent thì có cách nào để số điện thoại của người đó cũng hiện lên không ạ ?

    • Dữ liệu bạn lấy lên có thể nhiều nhưng bạn có thể tùy chỉnh chỉ cho chọn 1 số trường nhất định, sau đó bạn vẫn có thể truy xuất các trường khác. Hoặc bạn có thể lấy được ID của Student rồi sau đó truy vấn tới Database để lấy số điện thoại

  27. Anh có thể hướng dẫn cụ thể cách tạo csdl chung thư mục với project được ko ạ? Em muốn tạo csdl chung thư mục với project để có thể đưa sang máy khác chạy được nhưng ở trong phần attach a database file thì phải chọn một csdl có sẵn, vậy phải làm sao để tạo csdl mới? Em tạo csdl bằng sql server, rồi copy file mdf đưa vào thư mục project rồi attach vào nhưng khi đưa sang máy khác chạy thì báo lỗi!!! Anh làm sao mà cái csdl của a đưa sang máy khác ko bị lỗi vậy?

    • Để tự động Attach database file trong thư mục riêng thì máy phải có cài đặt SQL Server Express, các phiên bản SQL Server khác sẽ không sử dụng được tính năng này. Hơn nữa trong Connection String bạn phải để đường dẫn AttachDbFilename=|DataDirectory|\DatabaseName.mdf để cho biết rằng file Database nằm trong thư mục App Data của project

      • máy em có cài sql server express rồi, ý em muốn hỏi là lúc tạo database bằng visual studio thì phải là sao? Hay là phải tao database từ sql server rồi copy file mdf ra thư mục project? Em thử tạo database từ sql server rồi copy file mdf đưa vào project sau đó attach vào project nhưng khi đưa sang máy khác thi không chạy được? mà em thử conpy cái file StudentDB.mdf của anh attach vào project rồi chạy thì đưa sang máy khác chạy được, em muốn hỏi cách tạo file mdf của anh là như thế nào? Cám ơn anh!

      • Tạo ở đâu cũng giống nhau thôi, em chú ý tới phiên bản giữa các máy xem có tương thích hay không. Nếu máy em cài SQL Server Express chạy được thì sang máy khác sẽ chạy được….

  28. Anh ơi, em muốn load dữ liệu từ bảng dữ liệu lên textbox. Anh xem hộ em đoạn code này với ạ.
    protected void Page_Load(object sender, EventArgs e)
    {
    try
    {
    string id = Request.QueryString.Get(“IDTin”);
    txtMaTin.Text = id;
    NewID = Convert.ToInt32(id);
    if (!Page.IsPostBack)
    {
    LoadDuLieu();
    }
    }
    catch { }
    }
    private int NewID = 0;

    public void LoadDuLieu()
    {
    try
    {
    string strconnect = ConfigurationManager.ConnectionStrings[“ConnectionString”].ConnectionString;
    SqlConnection cn = new SqlConnection(strconnect);
    cn.Open();
    SqlCommand cmd = new SqlCommand();
    string sql = “select * from tbltintuc where IDTin=”+NewID;
    cmd.CommandText=sql;
    cmd.Connection=cn;
    SqlDataReader dr = cmd.ExecuteReader();
    if (dr.Read())
    {
    txttieude.Text=dr[“TieuDe”].ToString();
    txtTomTat.Text = dr[“TomTat”].ToString();
    FCKeditor1.Value = dr[“NoiDung”].ToString();
    txtPath.Text=dr[“hinh”].ToString();
    }
    cn.Close();
    cmd.Dispose();
    }
    catch { }

    }
    Em viết như vậy mà không load được j cả! Anh xem giúp em nhé! Em cảm ơn anh nhiều ạ

    • Bạn nên sử dụng Visual Studio để debug thử xem nó có load được dữ liệu lên không đã, có thể nó kết nối không được nên chạy vào khối catch và không có dữ liệu nào được load lên

  29. Pingback: [ASP.NET] Sử dụng ObjectDataSource và SqlDataSource

  30. Bài viết này (Làm việc với cơ sở dữ liệu – ADO.NET) rất bổ ích và có ý nghĩa ứng dụng cao. Cảm ơn bạn.
    Mình đang phải làm 1 ứng dụng tương tự như trên nhưng ở dạng WebForm/ASP.NET để hiển thị số liệu từ GridView trong ASP.NET sang các textbox và cũng muốn ghi dữ liệu trên các textbox vào cơ sở dữ liệu SQL. Mình đã đọc bài “Sử dụng GridView trong ASP.NET” của bạn và cũng đã loay hoay mất rất nhiều thời gian để vận dụng các đoạn viết code của bạn vào việc hiển thị số liệu từ GridView trong ASP.NET sang các textbox nhưng vẫn chưa được. Rất mong bạn chỉ dẫn. Xin trân trọng cảm ơn.
    Đăng Khoa

  31. Have you ever thought about writing an e-book or guest authoring on other
    sites? I have a blog based on the same ideas you discuss and would really like to
    have you share some stories/information.
    I know my viewers would value your work. If you’re even remotely interested, feel free
    to shoot me an e mail.

  32. Pingback: Sử dụng GridView trong ASP.NET | fishgold192

Gửi phản hồi

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s