zoukankan      html  css  js  c++  java
  • ado.net中的 sqlconnection sqlcommand datareader dataset SqlDataAdapter之间的关系

    Connection: 
    和数据库交互,必须连接它。连接帮助指明数据库服务器、数据库名字、用户名、密码,和连接数据库所需要的其它参数。Connection对象会被Command对象使用,这样就能够知道是在哪个数据源上面执行命令。 

    Command: 

    Command对象就是用来执行数据库操作命令的。比如对数据库中数据表的插入,删除,更新等都要通过Command对象来实现的。可以执行查询(SELECT语句),执行插入(INSERT语句),执行更新(UPDATE语句),执行删除(DELETE语句)。这个对象是架构在Connection 对象上,也就是Command 对象是透过连结到数据源。

    DataReader: 
    当我们只需要循序的读取数据而不需要其它操作时,可以使用DataReader 对象。DataReader对象只是一次一笔向下循序的读取数据源中的数据,而且这些数据是只读的,并不允许作其它的操作。因为DataReader 在读取数据的时候限制了每次只读取一笔,而且只能只读,所以使用起来不但节省资源而且效率很好。使用DataReader 对象除了效率较好之外,因为不用把数据全部传回,故可以降低网络的负载。ADO.NET 使用Connection 对象来连接数据库,使用Command 或DataAdapter对象来执行SQL语句,并将执行的结果返回给DataReader 或 DataAdapter ,然后再使用取得的DataReader 或DataAdapter 对象操作数据结果。

    DataAdapter: 
    主要是在数据源以及DataSet 之间执行数据传输的工作,它可以透过Command 对象下达命令后,并将取得的数据放入DataSet 对象中。这个对象是架构在Command对象上,并提供了许多配合DataSet 使用的功能。

    DataSet:  DataSet对象是ADO.NET的核心,基于DataSet的数据模型才使得ADO.NET实现离线式数据操作模型。可以把从数据库中所查询到的数据保留起来,甚至可以将整个数据库显示出来。DataSet 的能力不只是可以储存多个Table 而已,还可以透过DataAdapter对象取得一些例如主键等的数据表结构,并可以记录数据表间的关联。这个对象架构在DataAdapter对象上,本身不具备和数据源沟通的能力;也就是说我们是将DataAdapter对象当做DataSet 对象以及数据源间传输数据的桥梁。 DataSet是存在于内存中的数据库,是专门用来处理数据保存体中读出的数据。它的优点就是离线式的,一点读取到数据源中的数据后,就在内存中建立数据库的副本,在此之后的操作,直到执行更新命令为止,所有的操作都是在内存中完成的。不管底层的数据库是哪种形式,DataSet的行为都是一致。其中比较常用的列表控件(DataGridView,ComboBox)。

     DataReader与DataAdapter和DataSet读取数据的区别

      DataReader:

            public static string strconn = "server=.;database=Test;uid=sa;pwd=123456";
            static void Main(string[] args)
            {
                SqlConnection conn = new SqlConnection(strconn);
                conn.Open();
                SqlCommand comm = new SqlCommand();
    
                comm.Connection = conn;
                comm.CommandText = "prcPageResult";
    
                SqlParameter[] prams = {
                    new SqlParameter("@currPage", "1"),
                    new SqlParameter("@showColumn", "*"),
                    new SqlParameter("@tabName", "test"),
                    new SqlParameter("@strCondition", ""),
                    new SqlParameter("@ascColumn", "ID"),
                    new SqlParameter("@bitOrderType", "0"),
                    new SqlParameter("@pkColumn", "ID"),
                    new SqlParameter("@pageSize", "5")
              };
                int j = 0;
                comm.Parameters.AddRange(prams);
                comm.CommandType = CommandType.StoredProcedure;
                List<testModel> entitylist = new List<testModel>();
                using (SqlDataReader reader = comm.ExecuteReader())
                {
    
                    while (reader.Read())
                    {
                        testModel entity = new testModel();
                        entity.ID = Convert.ToInt32(reader["ID"]);
                        entity.Name = reader["Name"].ToString();
                        entitylist.Add(entity);
                    }
                }
                for (int i = 0; i < entitylist.Count; i++)
                {
                    Console.WriteLine(entitylist[i].Name);
                }
    
                conn.Close();
                Console.Read();
    
            }

      DataAdapter和DataSet:

     public static string strconn = "server=.;database=Test;uid=sa;pwd=123456";
            static void Main(string[] args)
            {
                SqlConnection conn = new SqlConnection(strconn);
                conn.Open();
                SqlCommand comm = new SqlCommand();
    
                comm.Connection = conn;
                comm.CommandText = "prcPageResult";
    
                SqlParameter[] prams = {
                    new SqlParameter("@currPage", "1"),
                    new SqlParameter("@showColumn", "*"),
                    new SqlParameter("@tabName", "test"),
                    new SqlParameter("@strCondition", ""),
                    new SqlParameter("@ascColumn", "ID"),
                    new SqlParameter("@bitOrderType", "0"),
                    new SqlParameter("@pkColumn", "ID"),
                    new SqlParameter("@pageSize", "5")
              };
                comm.Parameters.AddRange(prams);
                comm.CommandType = CommandType.StoredProcedure;
    
                SqlDataAdapter da = new SqlDataAdapter(comm);
                DataSet ds = new DataSet();
                da.Fill(ds, "test");
                List<testModel> entitylist = new List<testModel>();
                
                foreach (DataRow item in ds.Tables[0].Rows)
                {
                    testModel entity = new testModel();
                    entity.ID = Convert.ToInt32(item["ID"]);
                    entity.Name = item["Name"].ToString() ;
                    entitylist.Add(entity);
                }
                conn.Close();
                Console.Read();
    
            }

    SqlDataAdapter概述

      SqlDataAdapter是 DataSet和 SQL Server之间的桥接器,用于检索和保存数据。SqlDataAdapter通过对数据源使用适当的Transact-SQL语句映射 Fill(它可更改DataSet中的数据以匹配数据源中的数据)和 Update(它可更改数据源中的数据以匹配 DataSet中的数据)来提供这一桥接。当SqlDataAdapter填充 DataSet时,它为返回的数据创建必需的表和列(如果这些表和列尚不存在)。

      我们可以通过以下三种方法来创建SqlDataAdapter对象:

      使用方法

      1、通过连接字符串和查询语句

      string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串

      strSql="SELECT * FROM 表名";

      SqlDataAdapter da=new SqlDataAdapter(strSql,strConn);

      DataSet ds=new DataSet();//创建DataSet实例

      da.Fill(ds,"自定义虚拟表名");//使用DataAdapter的Fill方法(填充),调用SELECT命令

      这种方法有一个潜在的缺陷。假设应用程序中需要多个SqlDataAdapter对象,用这种方式来创建的话,会导致创建每个SqlDataAdapter时,都同时创建一个新的SqlConnection对象,方法二可以解决这个问题

      2、通过查询语句和SqlConnection对象来创建

      string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串

      SqlConnection conn=new SqlConnection(strConn);

      string strSql="SELECT * FROM 表名";

      SqlDataAdapter da = new SqlDataAdapter(strSql, conn);

      DataSet ds=new DataSet();//创建DataSet实例

      da.Fill(ds,"自定义虚拟表名");//使用DataAdapter的Fill方法(填充),调用SELECT命令

      3、通过SqlCommand对象来创建

      string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串

      SqlConnection connSql=new SqlConnection (strConn); //Sql链接类的实例化

      connSql.Open ();//打开数据库

      //使用SqlDataAdapter时没有必要从Connection.open()打开,

      //SqlDataAdapter会自动打开关闭它。

      string strSql = "SELECT * FROM 表名"; //要执行的SQL语句

      SqlCommand cmd=new SqlCommand(strSql,connsql);

      SqlDataAdapter da=new SqlDataAdapter(cmd); //创建DataAdapter数据适配器实例

      DataSet ds=new DataSet();//创建DataSet实例

      da.Fill(ds,"自定义虚拟表名");//使用DataAdapter的Fill方法(填充),调用SELECT命令

      ConnSql.Close ();//关闭数据库

      SqlDataAdapter da=new SqlDataAdapter(strSQL,ConnSql); //创建DataAdapter数据适配器实例DataSet ds=new DataSet();//创建DataSet实例da.Fill(ds,"自定义虚拟表名");//使用DataAdapter的Fill方法(填充),调用SELECT命令ConnSql.Close ();//关闭数据库

      注意

      如果只需要执行SQL语句或SP,就没必要用到DataAdapter ,直接用SqlCommand的Execute系列方法就可以了。sqlDataadapter的作用是实现Dataset和DB之间的桥梁:比如将对DataSet的修改更新到数据库。

      SqlDataAdapter的UpdateCommand的执行机制是:当调用SqlDataAdapter.Update()时,检查DataSet中的所有行,然后对每一个修改过的Row执行SqlDataAdapter.UpdateCommand ,也就是说如果未修改DataSet中的数据,SqlDataAdapter.UpdateCommand不会执行。

      使用要点

      1、SqlDataAdapter内部通过SqlDataReader获取数据,而默认情况下SqlDataReader不能获知其查询语句对应的数据库表名,

      所以下面的代码:

      string strConn = "uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串

      strSql="SELECT * FROM 表名";

      SqlDataAdapter da = new SqlDataAdapter(strSql,strConn);

      DataSet ds = new DataSet();

      da.Fill(ds);

      会在DataSet中创建一个新的DataTable,这个新的DataTable会拥有名为CustomerID和CompanyName 列,但是DataTable对象的名称是Table,而不是我们希望的Customers。

      这个问题,可以通过添加TableMapping来解决:

      string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串

      strSql="SELECT * FROM 表名";

      SqlDataAdapter da=new SqlDataAdapter(strSQL,strConn);

      da.TableMappings.Add("Table","Customers"); // 设置对象名称

      DataSet ds=new DataSet();

      da.Fill(ds);

      其实最简洁的方法是通过使用Fill方法的重载,通过指定DataTable,像这样:

      SqlDataAdapter.Fill(DataSet,"MyTableName");

      这样就可以不必使用TableMappings集合。

      2、在使用Fill方式时,可以指定DataTable,而不是DataSet:

      string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串

      strSql="SELECT * FROM 表名";

      SqlDataAdapter da = new SqlDataAdapter(strSql, strConn);

      DataTable tbl=new DataTable( );

      da.Fill(tbl);

      3、注意打开和关闭连接的处理

      在调用SqlCommand对象执行sql命令之前,需要保证与该对象关联的SqlConnection对象时打开的,否则SqlCommand的方法执行时将引发一个异常,但是我们在上面的代码中看到,SqlDataAdapter没有这样的要求。

      如果调用SqlDataAdapter的Fill方法,并且其SelectCommand属性的SqlConnection是关闭状态,则SqlDataAdapter会自动打开它,然后提交查询,获取结果,最后关闭连接。如果在调用Fill方法前,SqlConnection是打开的,则查询执行完毕后,SqlConnection还将是打开的,也就是说SqlDataAdapter会保证SqlConnection的状态恢复到原来的情形。

      这有时会导致性能问题,需要注意,例如下面的代码:

      string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串

      SqlConnection conn=new SqlConnection(strConn);

      SqlDataAdapter daCustomers,daOrders;

      strSql="SELECT * FROM Customers";

      daCustomers = new SqlDataAdapter(strSql, conn);

      strSql="SELECT * FROM Orders";

      daOrders=new SqlDataAdapter(strSql, conn);

      DataSet ds=new DataSet();

      daCustomers.Fill(ds,"Customers");

      daOrders.Fill(ds,"Orders");

      以上代码会导致连接被打开和关闭两次,在调用Fill方法时各一次。为了避免打开和关闭SqlConnection对象,在调用SqlDataAdapter对象的Fill方法之前,我们可以先打开SqlConnection对象,如果希望之后关闭连接,我们可以再调用Close方法,就像这样:

      cn.Open();

      daCustomers.Fill(ds,"Customers");

      daOrders.Fill(ds,"Orders");

      cn.Close();

      4、多次调用Fill方法需要注意数据重复和有效更新数据的问题

      string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串

      strSql="SELECT * FROM Customers";

      SqlDataAdapter da=new SqlDataAdapter(strSql, strConn);

      DataSet ds=new DataSet();

      da.Fill(ds,"Customers");

      //…….

      da.Fill(ds,"Customers");

      我们分析上面的代码,通过两次调用Fill方法,SqlDataAdapter执行两次查询,并两次将查询结果保存到DataSet中,第一次调用在DataSet中创建了一个名为Customers的新表。第二次调用Fill方法将查询的结果追加到DataSet中的同一个表中,因此,每个客户的信息将在DataSet中出现两次!当然,如果数据库管理员对Customers表定义了主键,则SqlDataAdapter在天成DataTable时,会判断重复行,并自动丢弃掉旧的值。

      考虑一下,假定一个特定客户在第一次调用Fill方法时,存储于数据库中,那么SqlDataAdapter会将其添加到新建的DataTable中。如果后来这个客户被删除了,那么第二次调用Fill方法时,SqlDataAdapter将不会在查询结果中找到该客户信息,但是它也不会将客户信息从DataSet中删除。这就导致了数据更新的问题。

      所以推荐的做法是,在调用Fill方法前,先删除本地DataSet中缓存的数据!

     转自:http://blog.csdn.net/chelen_jak/article/details/46821817

    ADO种的增删改查

      新增:

      SqlConnection conn= new SqlConnection(connectionStr);            //建立连接
      conn.Open();                                                      //打开数据库连接
      string sqlStr = "(SQL执行语句,例如  insert into A  values('abc',1))";    //定义相关的执行语句,相当于写好命令
      SqlCommand command1 = new SqlCommand(sqlStr, conn);          //构造函数指定命令对象所使用的连接对象connection1以及命令文本sqlStr ,相当于让系统接受命令。
      command1.ExecuteNonQuery();                                   //ExecuteNonQuery()方法返回值受影响的记录条数为一整数,代表操作所影响到的行数,注意ExecuteNonQuery()方法一般用于执行 UPDATE、INSERT、DELETE等非查询语句                                                                                                            // UPDATE、INSERT、DELETE等非查询语句,可以理解为让系统执行命令
      conn.Close();     ///关闭数据库连接

      修改:

    string connectionStr = "Data source=.;Initial Catalog=Student; Integrated Security=True";
    SqlConnection connection = new SqlConnection(connectionStr);
    string sqlStr = "update Course set Ccredit=5 where Cname='线性代数'";
    SqlCommand command1= new SqlCommand(sqlStr, connection);
    connection .Open();
    if (command1.ExecuteNonQuery() > 0)
    {
    MessageBox.Show("学分修改成功!");
    };
    connection .Close();

      删除:

    string connectionStr = "Data source=.;Initial Catalog=Student; Integrated Security=True";
    SqlConnection connection = new SqlConnection(connectionStr);
    string sqlStr = "DELETE FROM Person WHERE LastName = 'Wilson' ";
    SqlCommand command1
    = new SqlCommand(sqlStr, connection);
    connection .Open();

    if (command1.ExecuteNonQuery() > 0)
    {
      MessageBox.Show(
    "删除成功!");
    };
    connection .Close();
  • 相关阅读:
    htnl类名命规范
    JAVA集合中泛型的原理本质简介
    java 泛型中的上界(extend)和下界(super)
    elasticsearch深度分页问题
    AOP组合使用切面和自定义注解
    G1垃圾回收器基本知识及原理解析
    MyBatisplus源码解析
    生产环境碰到系统CPU飙高和频繁GC,你要怎么排查?
    fullgc触发条件_记一次生产频繁出现 Full GC 的 GC日志图文详解
    JavaThreadContextLoader(线程上线文类加载器)总结
  • 原文地址:https://www.cnblogs.com/liubaojing/p/8137613.html
Copyright © 2011-2022 走看看