ADO.Net中DataSet的应用

一、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);        //显示内容
                    }
                }
            }
        }

private void bt_领药出库_Click(object sender, EventArgs e)
{
SqlConnection sqlConnection = new SqlConnection(); //声明并实例化SQL连接;
sqlConnection.ConnectionString =
"Server=(local);Database=AddressList;Integrated Security=sspi"; //在字符串变量中,描述连接字符串所需的服务器地址、数据库名称、集成安全性(即是否使用Windows验证);
SqlCommand sqlCommand = sqlConnection.CreateCommand(); //调用SQL连接的方法CreateCommand来创建SQL命令;该命令将绑定SQL连接;
sqlCommand.CommandText =
"INSERT tb_病区药品 (姓名,所属病区,科室,领药时间,药品名称,剂型,领药医生) VALUES(@姓名,@所属病区,@科室,@领药时间,@药品名称,@剂型,@领药医生);"; //指定SQL命令的命令文本;命令文本包含参数;
sqlCommand.Parameters.AddWithValue("@姓名", this.txt_姓名.Text.Trim()); //向SQL命令的参数集合添加参数的名称、值;
sqlCommand.Parameters.AddWithValue("@所属病区", this.cmb_病区.Text.Trim());
sqlCommand.Parameters.AddWithValue("@科室", this.cmb_科室.Text.Trim()); //向SQL命令的参数集合添加参数的名称、值;
sqlCommand.Parameters.AddWithValue("@领药时间", this.dateTimePicker1.Text.Trim());
sqlCommand.Parameters.AddWithValue("@药品名称", this.txt_领药名称.Text.Trim()); //向SQL命令的参数集合添加参数的名称、值;
sqlCommand.Parameters.AddWithValue("@剂型", this.cmb_剂型.Text.Trim());
sqlCommand.Parameters.AddWithValue("@领药医生", this.txt_领药医生.Text.Trim());
//向SQL命令的参数集合添加参数的名称、值;
//SQL参数自动识别类型;若参数值为字符串,则类型自动设为NVARCHAR,且可在执行时自动转换;但对于相同密码,VARCHAR/NVARCHAR类型所获得的散列值不同,故需手动将SQL参数类型统一设为VARCHAR;
sqlConnection.Open(); //打开SQL连接;
int rowAffected = sqlCommand.ExecuteNonQuery(); //调用SQL命令的方法ExecuteNonQuery来执行命令,向数据库写入数据,并返回受影响行数;
sqlConnection.Close(); //关闭SQL连接;
MessageBox.Show("更新" + rowAffected.ToString() + "行,药品出库成功。");

}

 

 

二、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
    }

部分数据转载至这酸爽!

posted @ 2018-11-21 22:10  太阳公公是暖光!  阅读(134)  评论(0编辑  收藏  举报