五、弱類型DataSet(代碼創建)
1. 本地DataSet
A. 在內在中存儲數據,修改立即生效
DataTable customersTable = new DataTable("Customers");
customersTable.Columns.Add("ID", typeof(int));
customersTable.Columns.Add("Name", typeof(string));
DataRow oneRow = customersTable.NewRow();
oneRow["ID"] = 0;
oneRow[1] = "Jack";
DataColumn column = customersTable.Columns[0];
oneRow[column] = 1;
customersTable.Rows.Add(oneRow);
customersTable.Rows.Add(new object[] {2, "Fred"});
oneRow.BeginEdit();
oneRow[0] = 3; // 沒有改變,仍爲1
oneRow.CancelEdit(); // 恢復到BeginEdit時的值
foreach (DataRow row in customersTable.Rows)
{
Console.WriteLine(row[0] + " " + row["Name"]);
}
B. 在內在中存儲數據,修改批量生效
DataTable customersTable = new DataTable("Customers");
// do something to customersTable
customersTable.AcceptChanges(); // 提交所有行的更改
customersTable.RejectChanges(); // 拒絕最後一次提交後的更改
立即生效,馬上驗證數據有效性:
DataTable customersTable = new DataTable("Customers");
DataColumn column = customersTable.Columns.Add("Name", typeof(string));
column.MaxLength = 3;
DataRow oneRow = customersTable.NewRow();
customersTable.Rows.Add(oneRow);
oneRow["Name"] = "Jack123456"; // 這行拋異常,字符串超長
下面代碼說明,行的BeginEdit()到EndEdit()之間,對行數據的修改,若導致數據不完整或違反其他規則,不拋出異常,也不直接修改表中數據。此間可以通過CancelEdit()回滾修改。行的EndEdit()被調用,才批量驗證數據有效性。但修改仍未生效。
直到調用行或表級別上的AcceptChanges()時,數據才被批量提交。在表、行級別上調用AcceptChanges(),自動執行EndEdit();調用RejectChanges()時,自動調用CancelEdit()。
DataTable customersTable = new DataTable("Customers");
DataColumn column = customersTable.Columns.Add("Name", typeof(string));
column.MaxLength = 3;
DataRow oneRow = customersTable.NewRow();
customersTable.Rows.Add(oneRow);
oneRow.BeginEdit();
oneRow["Name"] = "Jack123456"; // 這行不拋異常
oneRow.EndEdit(); // 這行拋異常,字符串超長
customersTable.AcceptChanges();
C. DataSet
DataTable customersTable = new DataTable("Customers");
DataSet dataSet = new DataSet();
dataSet.Tables.Add(customersTable);
D. 聚合計算
DataTable customersTable = new DataTable("Customers");
customersTable.Columns.Add("Nmae", typeof(string));
customersTable.Columns.Add("Salary", typeof(float));
customersTable.Rows.Add(new object[] { "Jack", 8000 });
customersTable.Rows.Add(new object[] { "Tommy", 3500 });
float result = (float)customersTable.Compute("Sum(Salary)", "");
Console.WriteLine(result);
2. 數據業務規則驗證
DataTable customersTable = new DataTable("Customers");
// 驗證事件
customersTable.ColumnChanging += (sender, e) => {
if (e.Column.ColumnName == "Age")
{
// ProposedValue:已被更改後的值,但未生效
if ((int)e.ProposedValue < 0 || (int)e.ProposedValue > 100)
{
e.Row.SetColumnError(e.Column, "年齡超限");
}
}
};
DataColumn column = customersTable.Columns.Add("Age", typeof(int));
DataRow oneRow = customersTable.NewRow();
customersTable.Rows.Add(oneRow);
oneRow.ClearErrors();
oneRow.BeginEdit();
oneRow["Age"] = 105;
// 行級別監視
if (oneRow.HasErrors)
{
// show error
oneRow.CancelEdit();
}
else
{
oneRow.EndEdit();
}
// 表級別監視
if (customersTable.HasErrors)
{
DataRow[] errorRows = customersTable.GetErrors();
// show error
string errorRowText = errorRows[0].GetColumnError(0);
Console.WriteLine(errorRowText);
customersTable.RejectChanges();
}
else
{
customersTable.AcceptChanges();
}
3. 數據提取
A. 主鍵搜索
DataTable customersTable = new DataTable("Customers");
DataColumn column = customersTable.Columns.Add("ID", typeof(int));
customersTable.Columns.Add("name", typeof(string));
// 只能在主鍵上搜索
customersTable.PrimaryKey = new DataColumn[] { column };
customersTable.Rows.Add(new object[] {1, "Jack"});
DataRow row = customersTable.Rows.Find(1);
Console.WriteLine(row[1]);
B. 搜索條件
DataTable customersTable = new DataTable("Customers");
customersTable.Columns.Add("ID", typeof(int));
DataColumn column = customersTable.Columns.Add("name", typeof(string));
customersTable.Rows.Add(new object[] {100, "Jack"});
DataRow[] rows = customersTable.Select("name = 'Jack'");
if (rows.Length > 0)
{
Console.WriteLine(rows[0][0]);
}
4. DataView
DataTable包含實際的DataRow實例,DataView不包含DataRow實例,而包含了引用實際DataRow索引,指向各行。
DataTable employeesTable = new DataTable("Customers");
employeesTable.Columns.Add("Nmae", typeof(string));
employeesTable.Columns.Add("Salary", typeof(float));
employeesTable.Rows.Add(new object[] { "Jack", 8000 });
employeesTable.Rows.Add(new object[] { "Tommy", 3500 });
DataView view = new DataView(employeesTable);
view.RowFilter = "Salary > 0";
view.Sort = "Salary";
Console.WriteLine(view[0][0]);
Console.WriteLine(view[1][0]);
5. 讀取外部數據
從外存(數據庫)載入數據到內存(DataSet、DataTable)。
DataTable userTable = new DataTable();
DataSet dataSet = new DataSet();
using (SqlConnection conn = new SqlConnection(
"Data Source=localhost;Initial Catalog=SettingKnowledgeManagement;Integrated Security=True"))
{
SqlDataAdapter adapter = new SqlDataAdapter("select * from tb_user", conn);
// 或:
//SqlDataAdapter adapter2 = new SqlDataAdapter();
//adapter2.SelectCommand = new SqlCommand("select * from user", conn);
// Fill方法會自動打開數據庫連接,完成後自動關閉
adapter.Fill(userTable);
adapter.Fill(dataSet, "userTable");
}
6. 數據更新
A. 將數據存回數據庫
DataTable userTable = new DataTable();
using (SqlConnection conn = new SqlConnection(
"Data Source=localhost;Initial Catalog=SettingKnowledgeManagement;Integrated Security=True"))
{
SqlDataAdapter adapter = new SqlDataAdapter();
SqlCommand cmd = new SqlCommand("select * from tb_user", conn);
adapter.SelectCommand = cmd;
adapter.Fill(userTable);
cmd = new SqlCommand("insert into tb_user values(@username, @password)", conn);
// 返回自動編號需加此:
// cmd = new SqlCommand("insert into tb_user values(@username, @password); set @ID = @@IDENTITY;", conn);
cmd.Parameters.Add("@username", SqlDbType.VarChar, 255, "your name");
cmd.Parameters.Add("@password", SqlDbType.VarChar, 255, "your password");
// 返回自動編號需加此:
//SqlParameter returnParam = cmd.Parameters.Add("@ID", SqlDbType.BigInt, 0, "id");
//returnParam.Direction = ParameterDirection.Output;
adapter.InsertCommand = cmd;
cmd = new SqlCommand("update tb_user set password = @password where username = @username", conn);
cmd.Parameters.Add("@username", SqlDbType.VarChar, 255, "username");
cmd.Parameters.Add("@password", SqlDbType.VarChar, 255, "password");
adapter.UpdateCommand = cmd;
cmd = new SqlCommand("delete from tb_user where username = @username", conn);
cmd.Parameters.Add("@username", SqlDbType.VarChar, 255, "username");
adapter.DeleteCommand = cmd;
DataRow[] rows = userTable.Select("username = 'your name'");
if (rows.Length > 0)
{
rows[0][1] = "your new password";
}
// 更新表到數據庫
adapter.Update(userTable);
userTable.AcceptChanges();
}
B. 自動生成更新命令
注意:只能生成單表查詢,不能有關聯表;表必須有主鍵或有唯一約束;列名不能包含空格。
DataTable userTable = new DataTable();
using (SqlConnection conn = new SqlConnection(
"Data Source=localhost;Initial Catalog=SettingKnowledgeManagement;Integrated Security=True"))
{
SqlDataAdapter adapter = new SqlDataAdapter();
// 指定select
adapter.SelectCommand = new SqlCommand("select * from tb_user", conn);
// 自動生成insert, update, delete命令,與select對應
SqlCommandBuilder builder = new SqlCommandBuilder(adapter);
adapter.Fill(userTable);
userTable.Rows.Add(new object[] {"Jack", "my password"});
adapter.Update(userTable);
userTable.AcceptChanges();
}