1. 程式人生 > >【ADO.NET】8、DataSet的使用

【ADO.NET】8、DataSet的使用

pub () 服務器 定義 讀取 rem 錯誤 無法 man

一、DataSet的查詢

SqlDataReader 適用於大型數據的讀取,它是一條一條的讀取,讀取出來的數據是存放在服務器上
當正在讀取數據的時候,突然與服務中斷,將無法讀取後面的數據
DataSet 適用於小型數據的讀取,它是一次將所有數據讀取並存放到本機程序的內存當中,占內存
當正在讀取數據的時候,突然與服務中斷,數據可繼續讀取

DataSet可存放若幹個表(DataTable),每個表有若幹個行(DataRow)

技術分享
    private void button3_Click(object sender, EventArgs e)  //單擊事件
        {
            string Str = ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString;
            using (SqlConnection conn = new SqlConnection(Str))
            {
                conn.Open();
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = "select * from T_Age";
                    DataSet dataset = new DataSet();      //創建一個DataSet集,用於存放查詢到的數據
                    SqlDataAdapter adapter = new SqlDataAdapter(cmd);  //指定要執行的語句
                    adapter.Fill(dataset);           //將查詢到的數據填充到dataset中
                    DataTable table = dataset.Tables[0]; //查詢第一張表
                    for (int i = 0; i < table.Rows.Count; i++)  //遍歷每一行,DataTable包含若幹個行
                    {
                        DataRow row = table.Rows[i];    //遍歷每一行,得到每一行的內容
                        string name = Convert.ToString(row["Name"]);  //查詢當前行的 Name 列的數據
                        MessageBox.Show(name);        //顯示內容
                    }
                }
            }
        }
技術分享

二、DataSet的更新

row["Name"]="xgao"; 更新行
table.Rows.Remove(); 刪除行
table.NewRow(); 新增行

技術分享
    private void button3_Click(object sender, EventArgs e)  //單擊事件
        {
            string Str = ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString;
            using (SqlConnection conn = new SqlConnection(Str))
            {
                conn.Open();
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = "select * from T_Age";
                    DataSet dataset = new DataSet();      
                    SqlDataAdapter adapter = new SqlDataAdapter(cmd);  
                    adapter.Fill(dataset);          
                    DataTable table = dataset.Tables[0]; 
                    DataRow row = table.Rows[0];  
            row["Name"]="小高";      //將第一行的 Name 字段,更改為 "小高"
            table.Rows.RemoveAt(1);    //刪除第二行
            DataRow dr = table.NewRow();//增加新行
                    
              SqlCommandBuilder builder = new SqlCommandBuilder(adapter) //自動生成操作命令
            
            adpter.Update(dataset);
                    }
                }
            }
        }
技術分享

三、VS自動生成強類型DataSet(類型化DataSet)

有XML架構(XSD)的DataSet
本質上就是DataSet,但多了一個架構的定義

添加 - 新建項 - 數據集
將表從服務器資源管理器拖放到DataSet(數據集)中,註意拖放過程是自動根據表結構生成強類型DataSet等類,
沒有把數據也拖過來,程序還是連的那個數據庫,自動將數據庫連接字符串寫在了App.Config中

註意:表一定要設置有主鍵,被取值的列一定要有值
弱點:當表的字段增加時,就需要重新配置生成

代碼中使用DataSet示例(mydo表): mydoTableAdapter adapter = new mydoTableAdapter();
如何得知Adapter的類名?選中DataSet中的下半部分的Adapter,Name屬性就是類名,需要右鍵點擊類名 - 解析
取得所有數據:adapter.GetData(),
例子程序:遍歷顯示所有數據
i<adapter.GetData().Count;
adapter.GetData()[i].Age;

常見問題:類名一般為: 表名+TableAdapter,表名+DataTable,表名+Row,然後用"解析"來填充類名

實驗一 :操作 mydo 表,遍歷出所有 username 字段的值 ----- 查詢

技術分享
        private void button7_Click(object sender, EventArgs e)
        {
            mydoTableAdapter adapter = new mydoTableAdapter();        //創建一個TableAdapter
            SQL封裝.DataSet1.mydoDataTable data = adapter.GetData();       //獲取數據,強類型DataTable
            for (int i = 0; i < data.Count; i++)                   //遍歷數據
            {
                SQL封裝.DataSet1.mydoRow userRow = data[i];         //取得一行
                MessageBox.Show(userRow.username);              //打印該行的username屬性
            }
        }
技術分享

SQL封裝.DataSet1.mydoDataTable //為什麽這麽長?因為 mydoDataTable 類是在 DataSet1 類裏面定義的

SQL封裝: 程序集名稱 namespace
DataSet1: 外部類的類名

實驗二:操作 T_Age 表,遍歷出所有 Name 與 Age 字段的值 ----- 查詢

技術分享
     private void button1_Click(object sender, EventArgs e)
        {
            T_AgeTableAdapter adapter = new T_AgeTableAdapter();
            wf強類型.T_Age.T_AgeDataTable myage = adapter.GetData();
            for (int i = 0; i < myage.Count; i++)
            {
                wf強類型.T_Age.T_AgeRow data = myage[i];
                string msg = string.Format("姓名:{0},年齡:{1}", data.Name, data.Age);
                MessageBox.Show(msg);
            }
        }
技術分享

實驗三:操作 T_Age 表,修改T_Age表裏面的Name值 ------ 更新 Update

技術分享
       private void button1_Click(object sender, EventArgs e)
        {
            T_AgeTableAdapter adapter = new T_AgeTableAdapter();
            wf強類型.T_Age.T_AgeDataTable myage = adpater.GetData();
            for (int i = 0; i < myage.Count; i++)
            {
                wf強類型.T_Age.T_AgeRow data = myage[i];
                string msg = string.Format("姓名:{0},年齡:{1}", data.Name, data.Age);
                MessageBox.Show(msg);
            }
          myage[0].Name = "test";    //將表的Name字段的第一條數據改為 test
          adapter.Update(myage);    //針對myage表更新數據到服務器上
        }
技術分享

常見問題:錯誤提示:當傳遞有已修改行的DataRow集合時,更新要求有交接的UpdateCommand
原因:表中沒有加主鍵,為表中某個字段設置為主鍵即可

實驗四:操作 T_Age 表,往 Name 與 Age 字段插入值 ------- 插入 Insert

技術分享
       private void button3_Click(object sender, EventArgs e)
        {
            T_AgeTableAdapter adapter = new T_AgeTableAdapter();
            adapter.Insert("zhangsan", 23);    //直接調用 insert() 方法就可以插入數據
            MessageBox.Show("插入成功!");
        }
技術分享

實驗五:操作 T_Age 表,刪除表裏面的某行數據 ------- 刪除 delete

技術分享
        private void button3_Click(object sender, EventArgs e)
        {
            T_AgeTableAdapter adapter = new T_AgeTableAdapter();
            adapter.delete(3,"zhangsan", 23);    //刪除指定的數據,比較麻煩,都須要指定
            MessageBox.Show("刪除成功!");
        }
技術分享

//----------------強類型 DataSet數據的讀取

// 強類型 DataSet

技術分享
NewsDataSet ds = new NewsDataSet();
var daNews = new NewsDataSetTableAdapters.newsTableAdapter();
var daCate = new NewsDataSetTableAdapters.categoryTableAdapter();

daNews.Fill(ds.news);
daCate.Fill(ds.category);

this.gv1.DataSource = ds.category;
this.gv1.DataBind();

this.gv2.DataSource = ds.news;
this.gv2.DataBind();
技術分享

//---------------- 更精簡的 強類型 DataSet數據的讀取

this.gv1.DataSource = new NewsDataSetTableAdapters.categoryTableAdapter().GetCate();
this.gv1.DataBind();

//----------------強類型 DataSet 的插入,刪除,更改

new NewsDataSetTableAdapters.categoryTableAdapter().Insert("測試類型");
new NewsDataSetTableAdapters.categoryTableAdapter().Delete(13);
new NewsDataSetTableAdapters.categoryTableAdapter().Update("修改後的", 16);

四、為類型化DataSet增加自己的SQL語句

1.在數據集當中 右鍵 - 添加 - Query - 使用 SQL 語句 選擇操作的類型,如:select,insert,update,delete
如下:保存名為 GetDataByAge
SELECT id, Name, Age FROM T_Age WHERE (Age > @Age)

2.使用

技術分享
T_AgeTableAdapter adapter = new T_AgeTableAdapter();
wf強類型DataSet.T_Age.T_AgeDataTable data = adapter.GetDataByAge(30);   //傳值    
for (int i = 0; i < data.Count; i++)
{
    wf強類型DataSet.T_Age.T_AgeRow p = data[i];    //只輸出年齡大於 30 的
    MessageBox.Show(p.Name);
}
技術分享

五、優化強類型DataSet批量插入數據的時間

在強類型DataSet中,裏面所用到的 adapter.Insert(),之類的對數據庫進行操作的,它的工作模式如下:

1.插入數據前,先判斷連接是否打開,如果沒打開,則打開
2.完成數據插入後,再判斷,原先(不是程序自動打開的那個)的連接是否關閉,如果關閉則關閉,否則將繼續打開

默認連接是關閉的,所以當插入數據的時候會這樣工作:

1.自動打開連接,插入數據
2.完成數據插入後,發現原現的連接是關閉的,所以則關閉

從中可以看出我們只要在程序判斷前,將連接打開,後面程序將不會自動關閉連接,如果在做批量插入的時候,可以在循環語句前,先將連接打開,循環後,再將連接關閉,這樣將會大大加快數據的插入所耗時間

實例:
新建一個 Stopwatch 表,字段為 id int,Name nvarchar(20),Age nvarchar(20)

沒有做優化前,總耗時 12 秒, 做優化後,總耗時 2 秒

技術分享
private void button1_Click(object sender, EventArgs e)                //單擊事件
{
    Stopwatch sw = new Stopwatch();
    sw.Start();

    StopwatchTableAdapter adapter = new StopwatchTableAdapter();

    adapter.Connection.Open();                         //循環前,先打開連接
    for (int i = 0; i < 3000; i++)
    {
    adapter.Insert(i.ToString(), i.ToString(), i.ToString());    //插入數據
    }
    adapter.Connection.Close();            //循環後,再關閉連接
    sw.Stop();
    MessageBox.Show(sw.Elapsed.ToString());    //輸出耗時時間,以秒為單位
}
技術分享

在已建好的DataTable中添加一列數據

技術分享
  public DataTable GetOneTwoNum() 
    {
        DataTable dt = SoftwareTypeBLL.GetOneTwoNum();    // 獲得一個DataTable
        DataColumn dc = new DataColumn("TwoName", typeof(System.String));  // 設置一列
        dt.Columns.Add(dc);    // 將一列添加到 Datatable 中

        foreach (DataRow row in dt.Rows)
        {
            string TwoStr = "隨便內容";
            row["TwoName"] = TwoStr;    // 將新內容添加到指定的列
        }
        return dt;    //返回修改後的 DataTable
    }
技術分享

【ADO.NET】8、DataSet的使用