text:
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:
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
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
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:
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).
-
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.
Table này sẽ có các cột như sau:
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:
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
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.
-
studentID và add: 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 gridStudent là ds.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:
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:
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.
-
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;
-
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ứ?)
-
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() và 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 Replies to “Làm việc với cơ sở dữ liệu – ADO.NET”
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 ?
Em kiểm tra lại để chắc chắn là đã gọi phương thức Update của DataAdapter. Em có thể post đoạn code dùng để Xóa của em lên đây để a kiểm tra.
đâ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
Sorry em. Em sửa dòng ds.Tables[“Student”].Rows.Remove(dr) thành dr.Delete() nhé. Cảm ơn e vì đã chỉ ra lỗi… ^_^
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
Anh ơi cho em hỏi. Sao để tuổi anh là 17 tuổi zậy. 😀
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.
e camr ơn anh nhiều
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
Đổi tên file 😀
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à
Anh bận hả. Sao anh không trả lời.
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,
Dữ dội quá. Bài viết hay lắm ông !
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é!
Mình làm được rồi!
Xin cảm ơn!
Sao mỗi lần Delete Row thì nó báo lỗi ở dòng dr.Delete(); trong hàm btn_Delete() vậy bạn
Bạn nêu rõ lỗi gì để mình biết nhá, chứ chung chung thế này thì mình cũng không chắc là lỗi gì. Cảm ơn
cho minh hoi lam sao de insert 1 dong moi trong dataGridview?
vi no cu bao loi la data is bound.thank ban nha!!!
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,
Mong bạn giúp đỡ!!! thank!!!
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?
Connection String trên mỗi máy có thể không giống nhau tùy thuộc vào phiên bản SQL Server máy đó đang cài cũng như là thiết lập SQL Server đó. Bạn có thể tham khảo các dạng Connection String tại địa chỉ: http://connectionstrings.com/
Vậy có cách nào để sang máy khác mà project mình vẫn chạy khi có csdl không????
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
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
ID hiện tại = -1 là sao vậy a?
anh ơi cho em hỏi, em muốn tìm kiếm trong cơ sở dữ liệu một thông tin nào đó và cho nó hiện lên label thì sao ạ??
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.
http://www.mediafire.com/?tlnxwlv6n8pa9u8
Có gì bạn sửa rồi up lên lại cho mình nhé.
Cám ơn nhiều…
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
Anh oi cho em hoi the lam sao trong co so du lieu tu dong tang khoa co ca so va chu cai vi du la
A0001 A0002…..
Bạn có thể tham khảo bài viết này: http://www.sqlteam.com/article/custom-auto-generated-sequences-with-sql-server
bạn có thể cho mình yahoo đc không vậy? mình muốn hỏi nhiều hơn! thanks bạn vì bài này of bạn rất bổ ích!
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,
sao em ghi code giong vậy mà nó ko hiện thị vào datagridview vậy anh ơi
Anh co the viet nhieu bai ve .NET nua nhe
bai viet rat hay.minh moi hoc .net nhung cung thay hay lam….thanks
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)
Vậy bạn đang bí chỗ nào?
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”);
Bạn phải ghi rõ nội dung lỗi là gì thì mình mới giúp bạn được. Thân
LỖI MANV KHÔNG TỒN TẠI ĐÓ BẠN
MANV không tồn tại hình như là lỗi logic chứ không phải lỗi code
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
chỗ ds.Tables[“…”] của bạn có vấn đề vì bạn không đặt tên bảng, vì vậy bạn nên để là ds.Tables[0] để truy cập vào bảng trong dataset
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.
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!
Khi bạn tạo bảng thì bạn chỉ định khi delete sẽ xóa các mẩu tin ở bảng liên kết tới bằng “On Delete Cascade”. Ví dụ: http://www.java2s.com/Code/SQLServer/Constraints/DELETECASCADEandUPDATECASCADE.htm
Mình đã sửa được rồi, cảm ơn bạn rất nhiều!
Chúc bạn may mắn!
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….
ok cám ơn bạn để mình thử
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
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é
Bạn cần ghi rõ lỗi mà bạn gặp là gì thì mình mới có thể giúp được.
Thân
cho mình hỏi bạn có tài liệu ADO.net băng tiếng việt không?
Mình không có bạn ơi, bạn cố gắng đọc các tài liệu viết bằng tiếng Anh đi, cũng không khó hiểu lắm đâu…
Anh cho em hỏi làm sao đóng gói 1 chương trình mà có dùng cơ sở dữ liệu của sql?
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 !!!
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 !
Bạn có thể tham khảo các chuỗi kết nối ở trang web này: http://connectionstrings.com/, Data Source là chuỗi kết nối đến SQL Server Database (thường là .\SQLEXPRESS hoặc .\), AttachDbFilename là đường dẫn đến file database trên ổ cứng, Integrated Security là cho biết sẽ chứng thực theo cách nào (SQL hay là Windows). Bạn có thể tham khảo thêm tại: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.connectionstring(v=vs.71).aspx
Mình đã hiểu rồi, Cảm ơn ban nhiều nhe ! Bài của bạn rất bổ ích cho những người mới bước vào lập trình C# như mình !
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
Bạn làm không được phần nào? Kết nối dữ liệu, Tìm kiếm hay là hiển thị
Dạ, em đã làm được rồi ạ, cám ơn anh
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.
Bạn phải ghi lỗi chứ mình đoán mò cũng không ích gì…
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
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….
Cám ơn anh! 🙂
anh oi em attach du lieu vao CSDL k dk anh ah? anh viet 2005 hay 2008 vay?
Nếu nhớ không lầm thì là 2008
sao mình binding không được vậy bạn, có cần bỏ hàm binding vào form load ko bạn
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
Anh hướng dẫn cụ thể em được ko ạ? Em GÀ về khoản code này quá! 😦
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
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.

markdown:
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](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:
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**
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
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:
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).
-
**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**.
Table này sẽ có các cột như sau:
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:
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
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.
-
**studentID**và **add**: 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
**gridStudent** là **ds.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:
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:
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.
-
**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;
-
**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ứ?)
-
**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()**và **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](http://cid-cc33a58bacd7506c.office.live.com/self.aspx/.Public/ADONET.zip) **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 Replies to “Làm việc với cơ sở dữ liệu – ADO.NET”
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 ?
Em kiểm tra lại để chắc chắn là đã gọi phương thức Update của DataAdapter. Em có thể post đoạn code dùng để Xóa của em lên đây để a kiểm tra.
đâ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
Sorry em. Em sửa dòng ds.Tables[“Student”].Rows.Remove(dr) thành dr.Delete() nhé. Cảm ơn e vì đã chỉ ra lỗi… ^_^
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
Anh ơi cho em hỏi. Sao để tuổi anh là 17 tuổi zậy. 😀
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.
e camr ơn anh nhiều
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
Đổi tên file 😀
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à
Anh bận hả. Sao anh không trả lời.
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,
Dữ dội quá. Bài viết hay lắm ông !
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é!
Mình làm được rồi!
Xin cảm ơn!
Sao mỗi lần Delete Row thì nó báo lỗi ở dòng dr.Delete(); trong hàm btn_Delete() vậy bạn
Bạn nêu rõ lỗi gì để mình biết nhá, chứ chung chung thế này thì mình cũng không chắc là lỗi gì. Cảm ơn
cho minh hoi lam sao de insert 1 dong moi trong dataGridview?
vi no cu bao loi la data is bound.thank ban nha!!!
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,
Mong bạn giúp đỡ!!! thank!!!
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?
Connection String trên mỗi máy có thể không giống nhau tùy thuộc vào phiên bản SQL Server máy đó đang cài cũng như là thiết lập SQL Server đó. Bạn có thể tham khảo các dạng Connection String tại địa chỉ: http://connectionstrings.com/
Vậy có cách nào để sang máy khác mà project mình vẫn chạy khi có csdl không????
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
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
ID hiện tại = -1 là sao vậy a?
anh ơi cho em hỏi, em muốn tìm kiếm trong cơ sở dữ liệu một thông tin nào đó và cho nó hiện lên label thì sao ạ??
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.
http://www.mediafire.com/?tlnxwlv6n8pa9u8
Có gì bạn sửa rồi up lên lại cho mình nhé.
Cám ơn nhiều…
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
Anh oi cho em hoi the lam sao trong co so du lieu tu dong tang khoa co ca so va chu cai vi du la
A0001 A0002…..
Bạn có thể tham khảo bài viết này: http://www.sqlteam.com/article/custom-auto-generated-sequences-with-sql-server
bạn có thể cho mình yahoo đc không vậy? mình muốn hỏi nhiều hơn! thanks bạn vì bài này of bạn rất bổ ích!
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,
sao em ghi code giong vậy mà nó ko hiện thị vào datagridview vậy anh ơi
Anh co the viet nhieu bai ve .NET nua nhe
bai viet rat hay.minh moi hoc .net nhung cung thay hay lam….thanks
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)
Vậy bạn đang bí chỗ nào?
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”);
Bạn phải ghi rõ nội dung lỗi là gì thì mình mới giúp bạn được. Thân
LỖI MANV KHÔNG TỒN TẠI ĐÓ BẠN
MANV không tồn tại hình như là lỗi logic chứ không phải lỗi code
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
chỗ ds.Tables[“…”] của bạn có vấn đề vì bạn không đặt tên bảng, vì vậy bạn nên để là ds.Tables[0] để truy cập vào bảng trong dataset
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.
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!
Khi bạn tạo bảng thì bạn chỉ định khi delete sẽ xóa các mẩu tin ở bảng liên kết tới bằng “On Delete Cascade”. Ví dụ: http://www.java2s.com/Code/SQLServer/Constraints/DELETECASCADEandUPDATECASCADE.htm
Mình đã sửa được rồi, cảm ơn bạn rất nhiều!
Chúc bạn may mắn!
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….
ok cám ơn bạn để mình thử
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
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é
Bạn cần ghi rõ lỗi mà bạn gặp là gì thì mình mới có thể giúp được.
Thân
cho mình hỏi bạn có tài liệu ADO.net băng tiếng việt không?
Mình không có bạn ơi, bạn cố gắng đọc các tài liệu viết bằng tiếng Anh đi, cũng không khó hiểu lắm đâu…
Anh cho em hỏi làm sao đóng gói 1 chương trình mà có dùng cơ sở dữ liệu của sql?
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 !!!
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 !
Bạn có thể tham khảo các chuỗi kết nối ở trang web này: http://connectionstrings.com/, Data Source là chuỗi kết nối đến SQL Server Database (thường là .\SQLEXPRESS hoặc .\), AttachDbFilename là đường dẫn đến file database trên ổ cứng, Integrated Security là cho biết sẽ chứng thực theo cách nào (SQL hay là Windows). Bạn có thể tham khảo thêm tại: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.connectionstring(v=vs.71).aspx
Mình đã hiểu rồi, Cảm ơn ban nhiều nhe ! Bài của bạn rất bổ ích cho những người mới bước vào lập trình C# như mình !
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
Bạn làm không được phần nào? Kết nối dữ liệu, Tìm kiếm hay là hiển thị
Dạ, em đã làm được rồi ạ, cám ơn anh
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.
Bạn phải ghi lỗi chứ mình đoán mò cũng không ích gì…
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
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….
Cám ơn anh! 🙂
anh oi em attach du lieu vao CSDL k dk anh ah? anh viet 2005 hay 2008 vay?
Nếu nhớ không lầm thì là 2008
sao mình binding không được vậy bạn, có cần bỏ hàm binding vào form load ko bạn
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
Anh hướng dẫn cụ thể em được ko ạ? Em GÀ về khoản code này quá! 😦
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
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.

Vary: Cookie

X-hacker: If you're reading this, you should visit automattic.com/jobs and apply to join the fun, mention this header.

Link: <http://wp.me/p15Pzd-3i>; rel=shortlink

X-ac: 1.dca _dca


markdown:
### Chương 17: Hồi ức nho nhỏ….
Nghe nói Nam Tịch Tuyệt bị thương nằm viện, Tần Tiểu Mạn trong đầu bắt đầu tưởng tượng, đây chính là dấu hiệu bị trả thù rồi. Nam Tử thoạt nhìn có vẻ trung thực, thật ra cũng không phải là người tốt đâu.
Tần Tiểu Mạn nhìn máy in đang hoạt động, trầm tư suy nghĩ, quả nhiên không thể trông mặt mà bắt hình dong. Nam Tử chắc chắc cũng thuộc hàng phong lưu lãng tử. Anh so với Cố Lãng lại còn có phần phóng khoáng hơn, người ta bị anh ta làm cho to bụng, bây giờ con trai anh ta trở về báo thù. Nếu như cô mà là người bị anh ta bỏ rơi kia, cô tuyệt đối cũng sẽ không tha thứ cho anh ta.
Đàn ông ư? Tần Tiểu Mạn ngửa mặt lên nhìn trần nhà, giơ tay sờ sờ cục u trên đầu, sao đến bây giờ vẫn không chịu xẹp xuống a!
“Cốp”, một bàn tay khẽ gõ nhẹ lên đầu cô, tuy rằng rất nhẹ nhưng lại trúng ngay chỗ bị thương.
“A!” Tần Tiểu Mạn lập tức nhảy dựng lên, dọa Tô Lê Thâm sợ run, vôi vàng kéo cô, “Tiểu Mạn, có việc gì không? Xin lỗi!”
Tần Tiểu Mạn mắt rưng rưng nhìn Tô Lê Thâm đột nhiên xuất hiện thấy thật ký quái, sao gần đây lại gặp anh ta nhiều như vậy, như thế thật không tốt.
Tô Lê Thâm nhìn cô ôm đầu, giơ tay định xoa giúp cô. Có điều, tay chưa kịp chạm tới, một bàn tay thon dài đã túm chặt lấy cổ tay anh, “Tô tổng, như vậy không hay lắm đâu.”
Cố Lãng so với Tô Lê Thâm cao hơn một chút, hơn nữa lại đang ở địa bàn của mình, bộ dạng rõ ràng là cả vú lấp miệng em, Tần Tiểu Mạn liếc mắt nhìn, trò này anh làm cực giỏi luôn.
Tô Lê Thâm tức giận buông tay, khẽ cười, “Tôi đường đột rồi.” Lời còn chưa dứt, một ngón tay khác đã giơ lên chùi chùi vết trà còn dính trên miệng Tần Tiểu Mạn, “Lớn như vậy mà còn, tật ăn uống mãi không đổi.”
“Tô tổng tới đây không phải vì muốn làm phiền nhân viên của tôi chứ?” giọng nói Cố Lãng không tự chủ được có chút lạnh lùng. Nghiêm mặt nhìn Tô Lê Thâm rồi lại nhìn Tần Tiểu Mạn, càng nghĩ càng rầu. Cô từ lúc nào lại dây dưa với cái tên khó chơi như vậy?
Tô Lê Thâm lắc đầu, giơ một hộp quà lên đưa cho Cố Lãng, “Nghe nóiNamtổng không khỏe, tôi đại diện Tứ Hải đến thăm hỏi. Vừa lúc gặp Tiểu Mạn ở đây…” ánh mắt lại quay sang nhìn Tần Tiểu Mạn.
Cố Lãng bày ra bộ dáng mời đi, Tô Lê Thâm cũng không cách nào đành đi ra ngoài.
Tần Tiểu Mạn vội vã thu dọn đồ đạc trên bàn, cô hiện tại đã là thư ký của Cố Lãng, có rất nhiều thứ phải học. Cô không mong muốn cuộc sống hưởng thụ. Sách nói, kiếm tiền nuôi sống bản thân cũng là một thứ hạnh phúc. Tần Tiểu Mạn cô cũng muốn tự kiếm tiền, không muốn làm ký sinh trùng ăn bám.. Mặc dù cô ở Lăng Hiên sớm đã bị người ta nhìn bằng con mắt nhìn “kẻ giăng bẫy” rồi.
Trước mắt tối sầm lạị, Cố Lãng đột nhiên cúi xuống ép lên đôi môi của cô, hung hăng cắn một cái. Tần Tiểu Mạn muốn đẩy anh ra, lại bị anh túm lấy hai tay đặt trước ngực, đầu lưỡi dễ dàng tiến vào, công thành đoạt đất mạnh mẽ, khiến miệng cô có chút đau.
Tần Tiểu Mạn vô cùng xấu hổ, công ty lúc này nhiều người qua lại anh cũng không biết đường kiêng nể. Tô Lê Thâm ở trong kia vẫn còn chưa đi ra mà.
Cố Lãng hung hăng mút đôi môi của cô, dán vào lỗ tai nhẹ giọng, “Chính là muốn để anh ta nhìn!”
Tần Tiểu Mạn ngơ ngác nhìn theo bóng lưng Cố Lãng, một lúc lâu sau, mới có vẻ tỉnh ngộ =.,=.
—
Tan tầm, Cố Lãng đưa Tần Tiểu Mạn đi bộ sang ký túc xá của Lăng Hiên đối diện bệnh viện hỏi thăm Nam Tịch Tuyệt.
Ánh sáng mặt trời hắt bóng hai người trên mặt đất thật dài, lại gần, rồi lại đẩy ra xa, rồi lại gần…
Tần Tiểu Mạn vui vẻ, bộ dạng điên điên, đuổi theo cái bóng dài của Cố Lãng, cười thật sảng khoái.
Cố Lãng nhìn Tần Tiểu Mạn vui vẻ, nhớ tới lúc còn bé, khi cô học lớp 1, lưng đeo một chiếc cặp xách thật đo đựng đủ loại sách vở lật đật chạy theo anh. Cố Lãng chân dài, cô chân ngắn, hại cô đi vài bước phải đứng lại thở dốc, khuôn mặt bầu bĩnh lấm tấm mồ hôi. Lại thời gian sau nữa, anh lên trung học, Tần Tiểu Mạn cũng bắt đầu trưởng thành. Con gái phát triển rất nhanh, chỉ có một khoảng thời gian ngắn, cô đi cùng anh chỉ bị chậm lại một chút xíu.
Ở trường học, xung quanh Cố Lãng lúc nào cũng chất đầy đồ ăn vạt, Tần Tiểu Mạn thường mượn cớ nhờ anh dạy kèm, quấn quýt lấy để anh cho cô đồ ăn. Khẩu vị của cô rất kén, không được ăn cay, ăn cay nhiều dạ dày sẽ không chịu nổi. Cô thường vui sướng ăn một lèo thật no rồi lại vào wc để nôn ra. Vì chuyện này, anh đã từng bị cha sạc cho một trận.
Trường học của hai người rất gần nhau, mỗi ngày đều cùng nhau về nhà. Cho đến khi anh lên cấp ba, có một ngày, Tần Tiểu Mạn đột nhiên không muốn cùng anh đi nữa, nói là muốn đi với bạn. Cố Lãng cũng mặc kệ, khi đó anh còn ít tuổi, cũng không thích dắt theo con nít bên cạnh. Chỉ là, lúc chiều muộn về nhà, vẫn quen có nắm tay cùng đi, trong lòng thấy có chút cô đơn. Có đôi lúc, Cố Lãng vẫn nghĩ rằng Tần Tiểu Mạn đang ở phía sau, nhưng khi quay đầu lại chỉ thấy một con đường vắng vẻ.
Nhìn nụ cười của cô, lại để ý đến mái tóc rối do gió thổi, cũng đến lúc anh nên ổn định rồi. Lần này anh thực sự quyết tâm. Nhiều năm như vậy lăn lộn bên ngoài, anh đã không còn là người trong sạch. Kỳ thực, có nam nhân nào thành đạt mà hai bàn tay vẫn sạch sẽ như lúc đầu? Chỉ cần, người trong trái tim anh chịu tha thứ cho anh, mọi sự đều là không đáng kể.
Tần Tiểu Mạn đắc ý vênh váo, không để ý đến cục đá trên đường, “A” một tiếng rồi chới với trực ngã xuống, Cố Lãng vội vã giang tay ôm lấy eo của cô, “Cẩn thận một chút!”
Tần Tiểu Mạn thuận đà ôm lấy anh, cọ cọ má vào áo khoác của anh như muốn làm cho mòn luôn.
“Nhìn thật ngốc!” Cố Lãng búng nhẹ trán cô, thấy gương mặt nhỏ nhắn của ai đó bị gió làm cho khẽ ửng hổng, liền chỉnh lại khăn quàng cổ của cô, nắm lấy bàn tay lạnh lẽo đút vào túi mình.
“Cố Lãng.”
“Hả?”
“Hôm nay, là anh ghen phải không?” Tần Tiểu Mạn nhỏ giọng nói, mang theo chút đắc ý, cũng có chút bất an. Vốn dĩ, anh là sếp, cô là nhân viên, thân phận chênh lệch khiến cô có chút bất mãn, có điều, bây giờ thấy biểu hiện của anh, thật đúng là….
Cố Lãng dừng bước, khẽ vuốt vuốt khăn quàng cổ , nhìn ai đó khóe miệng còn chưa khép lại, “Tiểu Mạn, sau này cho dù thế nào, em cũng phải ở bên anh. Biết chưa?” Cố Lãng ôn nhu nói.
Tần Tiểu Mạn dịu dàng gật đầu. Đó là đương nhiên, giờ phút này, cô đã hiểu ra lời nói của An Nhiên, phải qua đau thương mới có được hạnh phúc. Chỉ là, cô không muốn nghĩ tới, bỗng dưng có một ngày lại như thế này, cô thà người ấy vô tâm vô phế, phong lưu đa tình, nếu như vậy, cô sẽ không yêu anh đến thế này…
—
* Bệnh viện…
Tần Tiểu Mạn gặp một người mà đánh chết cô cũng nghĩ không ra. Người kia thấy Tần Tiểu Mạn, ánh mắt hiện lên vẻ đau thương, tưởng như muốn nhào vào lòng cô khóc lớn lên, có điều, ánh mắt đó lúc dừng lại trên người Cố Lãng, lại nhất thời cụp xuống.
Cố Lãng có chút khó chịu, nắm lấy tay Tần Tiểu Mạn, ôm vào lòng.
“Cậu cùng với chồng nuôi từ bé ở chung một chỗ rồi sao?”
tem
=]]]]]] Piggy lai co tem oh la la *nhay mua sung suong* thanks Chuot ah,moak moak,nha Chuot post dung gio ghe lun
:*
thank nang hiiiiii
thank bạn ngơ
Chồng nuôi từ bé… Cute
ế lại có kịch hay hả * hai mắt long lanh*
hí ta cũng xương nàng chuột mừ * ôm ôm hun hun *
THANKS BAN
Ai dzay ta?
thanks nhieu nha 😉
thanks
Thanks ban chuot nhe, bay h hoi thich nam 9 mot teo, nhung truyen dai the nay, ko biet sau nay ntn?

WARC-Type: response

Content-Type: application/http; msgtype=response

WARC-Truncated: length

WARC-Identified-Payload-Type: text/html

Server: nginx

Connection: close

Link: <http://wp.me/p1g6Ff-2P>; rel=shortlink

Content-Type: text/html; charset=UTF-8


markdown:
Sau khi đi khai giảng năm học mới về, hai học sinh Trường Tiểu học Thạch Mỹ (Lộc Hà, Hà Tĩnh) đi chơi không may bị sảy chân xuống hồ nước sâu cùng tử vong.
Sự việc đau lòng xảy ra vào khoảng 8h10, sáng ngày 5.9, khi cháu Tô Văn Quân (SN 2010, học sinh lớp 1) và cháu Tô Thị Diễm Phương (SN 2009, học sinh lớp 2) cùng là học sinh Trường Tiểu học Thạch Mỹ đi khai giảng về rồi đi chơi thì bị sẩy chân ở hồ nước thuộc thôn Tân Phú khiến cả hai cùng chết đuối.
Anh Lê Văn Vị - người trực tiếp vớt hai học sinh trên cho biết, sau khi nghe tiếng kêu cứu, anh trực tiếp nhảy xuống hồ vớt cháu Diễm Phương lên bờ trước, sau đó tiếp tục lao xuống cứu cháu Quân nhưng đã quá muộn.
Theo người thân, Quân và Mỹ là anh em con chú con bác. Sau khi được bố mẹ đón đi khai giảng về, do còn sớm nên hai cháu rủ nhau đi chơi, không ngờ gặp nạn.
Theo một số người dân địa phương, từ năm 2015 đến nay, quá trình đào đất tạo thành hố sâu tại công trình thi công hệ thống kênh nước ngọt sông Nghèn đã khiến 6 người bị chết đuối.
|
|![]()
|
|Hồ nước nơi 2 học sinh bị nạn
|
|![]()
|
|Nhiều người đến chia buồn với gia đình nạn nhân

Set-Cookie: ldo_session=jUg3SVcvVzX1Q6NKuAJHvbzffmLvZnWTl6Z4aBMf; expires=Thu, 21-Sep-2017 19:47:44 GMT; Max-Age=7200; path=/; HttpOnly

Cache-Control: no-cache, private


text:
Nail kim tuyến đẹp là tuyển tập những mẫu móng tay xinh họa tiết thời trang thật phong cách và sành điệu mà các nàng nên chọn lựa áp dụng cho ngày đi tiệc cuối năm. Bên cạnh một bộ cánh lộng lẫy, lung linh và cực sang trọng, phái đẹp cũng nên tạo thêm sức hút tuyệt vời cho mình bằng một bộ móng thời thượng ánh kim tuyến thật kiêu sa và đài cát, chắc chắc bạn sẽ chinh phục được mọi ánh nhìn trong ngày đi tiệc nhiều quan khách đặc biệt đấy.
Nào hãy cùng mecuteo.vn ngắm nhìn những mẫu nail kim tuyến đẹp tuyệt vời và cực hấp dẫn xu hướng bên dưới đây nhé!
Với những mẫu nail kim tuyến đẹp lấp lánh, sang trọng và kiêu sa mà chúng tôi vừa giới thiệu trên đây, hi vọng rằng sẽ giúp các nàng có thể tham khảo mà chọn lựa áp dụng cho mình một kiểu móng tay thật ưng ý để tự tin tỏa sáng giữa bao người trong ngày dạ tiệc hè. Một chút nhấn nhá trên mẫu nail kim tuyến bằng cách đính thêm hạt, thêm những họa tiết hoa nổi sẽ cho bạn một đôi bàn tay xinh xắn đầy cuốn hút hơn bao giờ hết đấy. Hãy luôn đồng hành và ủng hộ Mecuteo nhé!

markdown:
**Nail kim tuyến **đẹp là tuyển tập những mẫu móng tay xinh họa tiết thời trang thật phong cách và sành điệu mà các nàng nên chọn lựa áp dụng cho ngày đi tiệc cuối năm. Bên cạnh một bộ cánh lộng lẫy, lung linh và cực sang trọng, phái đẹp cũng nên tạo thêm sức hút tuyệt vời cho mình bằng một bộ móng thời thượng ánh kim tuyến thật kiêu sa và đài cát, chắc chắc bạn sẽ chinh phục được mọi ánh nhìn trong ngày đi tiệc nhiều quan khách đặc biệt đấy.
Nào hãy cùng mecuteo.vn ngắm nhìn những mẫu nail kim tuyến đẹp tuyệt vời và cực hấp dẫn xu hướng bên dưới đây nhé!
*Với những mẫu nail kim tuyến đẹp lấp lánh, sang trọng và kiêu sa mà chúng tôi vừa giới thiệu trên đây, hi vọng rằng sẽ giúp các nàng có thể tham khảo mà chọn lựa áp dụng cho mình một kiểu móng tay thật ưng ý để tự tin tỏa sáng giữa bao người trong ngày dạ tiệc hè. Một chút nhấn nhá trên mẫu nail kim tuyến bằng cách đính thêm hạt, thêm những họa tiết hoa nổi sẽ cho bạn một đôi bàn tay xinh xắn đầy cuốn hút hơn bao giờ hết đấy. Hãy luôn đồng hành và ủng hộ Mecuteo nhé!* ![ �o so mi n? d?p th?i trang Luzy](https://mecuteo.vn/sp/ao/Ao-so-mi-nu-dep-thoi-trang-Luzy.jpg)
![ �o so mi n? d?p th?i trang Luzy](https://mecuteo.vn/sp/ao/Ao-so-mi-nu-dep-thoi-trang-Luzy.jpg)
![ V�y d?m d?p th?i trang Luzy](https://mecuteo.vn/sp/ao/Vay-Dam-Dep-thoi-trang-Luzy.jpg)
![ V�y d?m d?p th?i trang Luzy](https://mecuteo.vn/sp/ao/Vay-Dam-Dep-thoi-trang-Luzy.jpg)

Vary: Accept-Encoding, Cookie

Server: Nginx

X-Powered-By: VPSSIM

Strict-Transport-Security: max-age=31536000; includeSubdomains;

X-Frame-Options: SAMEORIGIN

X-Content-Type-Options: nosniff

X-XSS-Protection: 1; mode=block


text:
04/06/2014 1625
Chùa được Thiền sư Minh Lý xây dựng vào năm 1875. Chùa có kiến trúc hài hòa theo phong cách Á – Âu. Kiến trúc mặt tiền hiện nay được trùng tu vào năm 1970. Chùa có tấm bia ghi việc cụ Nguyễn Sinh Sắc đã ở chùa từ năm 1921 đến 1923.
Cổng Chùa Long Hưng - An Giang
Xem thêm: Các khách sạn giá rẻ tại An Giang
Ở chánh điện có nhiều pho tượng cổ như tượng đức Phật A Di Đà, bộ tượng Thập Điện Minh Vương...
Tượng Quan Thế Âm
Hai ngôi tháp mộ lớn ở chùa là tháp của Hòa thượng Thích Đạt Điền (đời 38) và Hòa thượng Thích Chơn Như (đời 40).
Chùa đã được Bộ Văn hóa – Thông tin công nhận là Di tích lịch sử – văn hóa quốc gia.
XEM BÁO GIÁ QUA EMAIL>

markdown:
04/06/2014 1625
Chùa được Thiền sư Minh Lý xây dựng vào năm 1875. Chùa có kiến trúc hài hòa theo phong cách Á – Âu. Kiến trúc mặt tiền hiện nay được trùng tu vào năm 1970. Chùa có tấm bia ghi việc cụ Nguyễn Sinh Sắc đã ở chùa từ năm 1921 đến 1923.
*Cổng Chùa Long Hưng - An Giang * **Xem thêm: ** *Các khách sạn giá rẻ tại An Giang*
Ở chánh điện có nhiều pho tượng cổ như tượng đức Phật A Di Đà, bộ tượng Thập Điện Minh Vương...
*Tượng Quan Thế Âm*
Hai ngôi tháp mộ lớn ở chùa là tháp của Hòa thượng Thích Đạt Điền (đời 38) và Hòa thượng Thích Chơn Như (đời 40).
Chùa đã được Bộ Văn hóa – Thông tin công nhận là Di tích lịch sử – văn hóa quốc gia.
XEM BÁO GIÁ QUA EMAIL>

Server: Apache/2.2.15 (CentOS)

Connection: Close

Pragma: no-cache

Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0

Vary: Accept-Encoding