1.连接字符串,我们可以高效的完成客户端同数据

作者: 编程  发布:2019-11-20

最近比较忙,好久没写博客了。个人感觉最好的进步就是写东西。哈哈。

转自:

通过ADO.NET技术,我们可以高效的完成客户端同数据库之间的数据访问操作,便于我们在客户端程序简便高效的访问以及获取数据库中的有用数据,同时也可以对数据库中的数据进行更新,即可以完成客户端与数据库之间的双向操作。本文简单介绍如何在客户端程序中利用ADO.NET技术来访问以及使用数据库中的数据。

一般我们使用ADO.net从数据库中读取数据返回的集合是DataSet类型的。有时候我们需要进行转换成List<T>集合。一般的做法是在DAL层中,写个方法进行转换。(每个表写一个)。累哦!~

目录:

ADO.NET对象模型的最主要的4个组成部分分别是:Connection(SqlConnection)、Command(SqlCommand)、DataReader(SqlDataReader)、DataAdapter(SqlDataAdapter)。下面我们将详细介绍这四种对象的基本用法和其常用的属性、方法以及如何利用它们来完成对数据库的访问操作。

所以我就想,能不能写个工厂,传入DataSet 集合 和 需要转化的类的类型。就自动转化了。就有了下面的代码了。

  1. 简单的介绍下ADO.NET
  2. SqlConnection(连接对象)
  3. SqlCommand(命令对象)
  4. SqlParameter(Sql参数)
  5. SqlDataReader(数据流读取器)
  6. SqlTransaction(事务)
  7. SqlDataAdapter(数据适配器)
  8. DataSet,DataTable,DataRow,DataColumn
  9. 封装数据库操作类(这才是精华) 

1.Connection(SqlConnection)

图片 1图片 2

一丶简单的介绍下ADO.NET

Connection对象位于最顶层,是所有数据访问请求的关口。简单来说,我们访问数据库中的数据的一般流程为:连接目标数据库 -> 执行访问命令(如结构化查询语言命令) -> 返回命令执行结果并进行处理 -> 关闭连接,而Connection对象就用于流程的第一步:连接目标数据库。

 1         /// <summary>
 2         ///  Dataset 集合根据传入的 类型。自动转换List集合"
 3         /// </summary>
 4         /// <typeparam name="T">类(属性类 modle)</typeparam>
 5         /// <param name="ds">数据集合</param>
 6         /// <returns>List集合</returns>
 7         public List<T> GetListbyDataSet<T>(DataSet ds) where T: new()
 8         {
 9             List<T> li = new List<T>(); //声明要返回的集合
10             var s = typeof(T);          // 获取传入类型
11             var str = s.GetProperties(); // 获取传入类型的属性集合
12             if (ds.Tables[0] == null || ds.Tables[0].Rows.Count < 0) //判断ds的null和是否包含数据
13             {
14                 return li;
15             }
16             for (int i = 0; i < ds.Tables[0].Rows.Count; i++) //循环集合准备获取数据
17             {
18                 T t1 = new T();       // 声明类
19                 foreach (var item in str)  // 循环类的属性
20                 {
21                     string itemstr = item.Name; //类属性名称
22                     var itemtype = item.PropertyType; // 类属性的类型(int string datetime)
23                     object value = GetvalbyDataSet(itemstr, itemtype, ds.Tables[0].Rows[i]); //获取值
24                     item.SetValue(t1, value, null);
25                     
26                 }
27                 li.Add(t1);
28             }
29              return li;
30         }

   了解System.Data命名空间下我们常用的一些类:

我们先看一下以下简单实例:

View Code

图片 3

图片 4图片 5

图片 6图片 7

 1 ①System.Data  → DataTable,DataSet,DataRow,DataColumn,DataRelation,Constraint,DataColumnMapping,DataTableMapping
 2 ②System.Data.Coummon     → 各种数据访问类的基类和接口
 3 ③System.Data.SqlClient   → 对Sql Server进行操作的数据访问类
 4   主要有:   a) SqlConnection            → 数据库连接器
 5             b) SqlCommand               → 数据库命名对象
 6             c) SqlCommandBuilder        → 生存SQL命令
 7             d) SqlDataReader            → 数据读取器
 8             e) SqlDataAdapter           → 数据适配器,填充DataSet
 9             f) SqlParameter             → 为存储过程定义参数
10             g) SqlTransaction           → 数据库事物
using System;using System.Data.SqlClient;namespace Test{    class Program    {        static void Main(string[] args)        {            SqlConnection mSqlConnection = new SqlConnection();            mSqlConnection.ConnectionString = "Data Source=SQLServerInstanceName;Initial Catalog=DBName;Integrated Security=SSPI;";            mSqlConnection.Open();            if (mSqlConnection.State == System.Data.ConnectionState.Open)            {                Console.WriteLine("Database Connection is Open");            }            mSqlConnection.Close();        }    }}
 1  /// <summary>
 2         ///  在DataRow中 获取 对应列的值
 3         /// </summary>
 4         /// <param name="colname">列名称</param>
 5         /// <param name="colname">列的类型</param>
 6         /// <param name="dr">DataRow 集合</param>
 7         /// <returns>列值</returns>
 8         private object GetvalbyDataSet(string colname,Type coltype, DataRow dr)
 9         {
10             if (dr.Table.Columns.Contains(colname))
11             {
12                 if (typeof(int) == coltype)
13                 {
14                     return dr[colname] == null ? 0 : int.Parse(dr[colname].ToString());
15                 }
16                 if (typeof(DateTime) == coltype)
17                 {
18                     return dr[colname] == null ? DateTime.Parse("2016/9/22") : DateTime.Parse(dr[colname].ToString());
19                 }
20                 if (typeof(decimal) == coltype)
21                 {
22                     return dr[colname] == null ? decimal.Parse("0") : decimal.Parse(dr[colname].ToString());
23                 }
24                 string str = dr[colname] == null ? "" :  dr[colname].ToString();
25                 return str;
26             }
27             else
28             {
29                 return "";
30             }
31         }

图片 8

View Code

View Code

  

首先,为了能够使用SqlConnection类,我们首先需要引用命名空间System.Data.SqlClient (using System.Data.SqlClient);接着创建SqlConnection类型的实例对象mSqlConnection,为其属性ConnectionString赋值连接字符串;然后调用Open()方法,这就完成了数据库的连接操作;最后记得在完成访问数据操作之后,调用Close()方法,关闭连接。

 

二丶SqlConnection(连接对象)

Connection对象具有多个属性以及方法,下面介绍最基础常用的属性以及方法:

  1.连接字符串

常用属性:

    基本语法:数据源(Data Source)+数据库名称(Initial Catalog)+用户名(User ID)+密码(Password)(这种方式比较安全)!

ConnectionString :获取或设置用来打开SQL Server数据库的连接字符串。

    推荐文章 :SQL Server 连接字符串和身份验证,你必须知道的ADO.NET(三) 连接字符串,你小觑了吗?,SQL Server 2008连接字符串写法大全,连接字符串有很多的写法,最保险的写法可以借助“SqlConnectionStringBuilder”类,它提供了全面的连接字符串的属性,以至于减少出错率(相关属性查MSDN),还有大多数连接字符串都写在配置文件里面了!

ConnectionTimeout:获取等待时间,即终止尝试连接操作或者返回错误信息之前的等待时间。

  2.创建连接对象

DataSource:获取要连接的SQL Server实例名称。

图片 9View Code

Database:获取数据库的名称。

  3.打开和关闭连接对象(使用Using来关闭连接)

常用方法:

图片 10View Code

Open():使用ConnectionString中指定的属性设置数据库连接。

     关于连接池的文章:你必须知道的ADO.NET(五) 细说数据库连接池(写的还真不赖啊),顶...

Close():关闭数据库连接。

 

我们在连接字符串中可以看到设置了Data Source、Initial Catalog以及Integrated Security三个值:Data Source表示要连接的SQL Server实例名称;Initial Catalog表示要访问的数据库名称;Integrated Security表示所采用的安全验证方式。

 三丶SqlCommand(命令对象)

Integrated Security设置为SSPI或者true,则表示采用Windows身份验证;否则表示采用SQL Server身份验证,此时就需要在连接字符串中设置User ID 和Password。

  1.实例化的时候默认初始化的四个属性

连接字符串的设置

图片 11

连接字符串既可以在ConnectionString属性中设置,也可以在创建SqlConnection实例对象时设置,还可以在配置文件中设置:

  2.创建命令对象

图片 12图片 13

    使用连接对象的“CreateCommand()”方法创建命令对象,也可以使用new来实例化对象!

using System;using System.Data.SqlClient;using System.Configuration;namespace Test{    class Program    {        static void Main(string[] args)        {            //1.ConnectionString属性设置            SqlConnection mSqlConnection = new SqlConnection();            mSqlConnection.ConnectionString = "Data Source=SQLServerInstanceName;Initial Catalog=DBName;Integrated Security=SSPI;";            //2.创建对象实例时设置            string connectionString1 = "Data Source=SQLServerInstanceName;Initial Catalog=DBName;Integrated Security=SSPI;";            SqlConnection mSqlConnection1 = new SqlConnection(connectionString1);            //3.配置文件中设置            string connectionString2 = ConfigurationManager.AppSettings["ConnectionString"].ToString();            SqlConnection mSqlConnection2 = new SqlConnection(connectionString2);        }    }}
1 SqlCommand command = connection.CreateCommand(); //这种方式比较好,也可以自己实例化一个对象!

View Code

  3.几个重要属性

配置文件如下:

    ①CommandText:获取或设置要对数据源执行的 Transact-SQL 语句、表名或存储过程!

图片 14图片 15

    ②CommandType:设置你执行的SQL语句是存储过程还是T-SQL(是一个枚举)!

<?xml version="1.0" encoding="utf-8" ?><configuration>    <appSettings>        <add key ="ConnectionString" value="Data Source=SQLServerInstanceName;Initial Catalog=DBName;Integrated Security=SSPI;" />    </appSettings>    <startup>         <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />    </startup></configuration>

    图片 16

View Code

    ③Parameters:设置你T-SQL中你需要用到的参数(后面会讲到),是一个“SqlParametersCollection”类型,这个属性很重要,是你通过代码给SQL语句传递参数的途径,所以记住语法,记住一些使用规则讲对编码有很大的帮助!

注意:获取配置文件中的连接字符串时首先需要引用System.Configuration (using System.Configuration)。

  4.几个重要的方法(相信大家熟悉的不能再熟悉了)

资源释放以及异常处理

    ①ExecuteNonQuery:返回是影响的行数(int),主要执行更新,添加,删除等操作!

数据库的连接操作是十分占用资源的,在使用完成之后一定要关闭连接,释放资源。一般调用Close()方法关闭连接,释放资源。但有时我们会忘记调用Close()方法,这就导致了资源的浪费。为了避免这种情况的发生,我们可以使用using来完成资源的释放。而对于异常处理,我们可以使用try{...}catch{...}操作,示例代码如下所示:

    ②ExecuteReader:执行SQL或存储过程,返回的是SqlDataReader类型,主要用来查询!

图片 17图片 18

      ★  这边注意这个方法的重载 CommandBehaviour 枚举,成员如下:

            try            {                string connectionString = ConfigurationManager.AppSettings["ConnectionString"].ToString();                using (SqlConnection mSqlConnection = new SqlConnection(connectionString))                {                    mSqlConnection.Open();                    if (mSqlConnection.State == ConnectionState.Open)                    {                        Console.WriteLine("Database Connection is Open");                    }                }            }            catch (SqlException e)            {                Console.WriteLine(e.Message);            }            catch (Exception ex)            {                Console.WriteLine(ex.Message);            }

    图片 19

View Code

1 command.ExecuteReader(CommandBehavior.CloseConnection); //在执行读取之后会自动关闭连接对象

对SqlConnection 实例对象mSqlConnection相关操作的进一步封装

     ③ExecuteScalar:返回执行结果集中的第一行第一列,如果没有数据,则返回NULL!

我们可以将对mSqlConnection的相关操作进一步提取封装到一个方法中,这样有利于代码的重用,示例如下所示:

     Note:因为可能会返回“Null”值,所以需要对结果进行判断,如下:

注意:下面的代码中我们将使用SqlConnectionStringBuilder对象来创建连接字符串。

图片 20View Code

图片 21图片 22

    ④CreateParameter:创建SqlParameter实例

    class Program    {        static void Main(string[] args)        {            try            {                using (SqlConnection mSqlConnection = GetSqlConnection("SQLServerInstanceName", "DatabaseName", "", "", true))                {                    if (mSqlConnection.State == ConnectionState.Open)                    {                        Console.WriteLine("Database Connection is Open");                    }                }            }            catch (SqlException e)            {                Console.WriteLine(e.Message);            }            catch (Exception ex)            {                Console.WriteLine(ex.Message);            }        }        public static SqlConnection GetSqlConnection(string server, string database, string userid, string password, bool integratedSecurity)        {            SqlConnection mSqlConnection = new SqlConnection();            mSqlConnection.ConnectionString = GetSqlConnectionString(server, database, userid, password, integratedSecurity);            mSqlConnection.Open();            return mSqlConnection;        }        public static string GetSqlConnectionString(string server, string database, string username, string password, bool ignoredUserId)        {            SqlConnectionStringBuilder mSqlConnectionStringBuilder = new SqlConnectionStringBuilder();            mSqlConnectionStringBuilder.DataSource = server;            mSqlConnectionStringBuilder.InitialCatalog = database;            if (!ignoredUserId && !string.IsNullOrEmpty && !string.IsNullOrEmpty)            {                mSqlConnectionStringBuilder.IntegratedSecurity = false;                mSqlConnectionStringBuilder.UserID = username;                mSqlConnectionStringBuilder.Password = password;            }            else            {                mSqlConnectionStringBuilder.IntegratedSecurity = true;            }            return mSqlConnectionStringBuilder.ConnectionString;        }    }
1 SqlParameter para = cmd.CreateParameter() //此方法适合SQL语句中只有一个参数的情况!

View Code

     推荐文章:你必须知道的ADO.NET(六) 谈谈Command对象与数据检索

2.Command(SqlCommand)

          你必须知道的ADO.NET(七) Wow!Command对象高级应用

当成功连接到数据库之后,接下来我们就要进行数据的访问操作了,比如对数据源的查询操作等,这时就需要使用Command对象了。

 

SqlCommand类最基本常用的属性和方法如下所示(其他的不在这里列举,读者可以自行查询):

四丶SqlParameter(Sql参数)

方法:

  1.几个重要的属性    

ExecuteNonQuery()::用于执行SQL语句,该方法用于不需要返回任何记录的情况。(例如,INSERT、DELETE或UPDATE查询)。

        ParameterName:   设置参数名

ExecuteReader():用于执行SQL语句并返回一组数据。

        Value:              给参数设置值

ExecuteScalar():用于执行查询,并返回查询所返回的结果集中第一行第一列的内容,其他内容将被忽略。

    Size:                 设置参数字节最大大小(以字节为但为)

ExecuteXmlReader():以XmlReader形式返回结果集。

    SqlDbType:     参数在SQL中的类型  

属性:

图片 23View Code

CommandText:设置对数据源执行的文本命令。

  2.命令对象添加参数集合的几种方法

CommandTimeout:等待时间。

    ①AddWithValue

CommandType:对CommandText属性的解释。(枚举,其中包括StoredProcedure、TableDirect和Text)。

    ②Add

Connection:数据库连接。

    ③AddRange

Parameters:Parameter对象的集合。

    推荐文章:SqlParameter的作用与用法,代码如下:

ExecuteReader()方法

图片 24

示例1:

 1  using (SqlConnection connection = new SqlConnection(""))
 2  {
 3      SqlCommand command = connection.CreateCommand();
 4      command.CommandText = "";
 5 
 6      //可以使用这种方式添加多个参数,不过方式不够好
 7      command.Parameters.Add("@name", SqlDbType.NVarChar).Value = "yang"; //第一种方式
 8      command.Parameters.Add("@age", SqlDbType.Int).Value = 888;
 9      command.Parameters.Add("@address", SqlDbType.NVarChar, 100).Value = "Jiang Su";
10 
11      //这种方式直接给定参数名和参数就可以了,可操作性比较差
12      command.Parameters.AddWithValue("@name", "yang");
13      command.Parameters.AddWithValue("@age", 888).SqlDbType = SqlDbType.Int;
14      command.Parameters.AddWithValue("@address", "Jiang su").SqlDbType = SqlDbType.NVarChar;
15 
16      //直接使用参数集合添加你需要的参数,推荐这种写法
17      SqlParameter[] parameters = new SqlParameter[]
18      {
19          new SqlParameter("@name",SqlDbType.NVarChar,100){Value = "yang"},
20          new SqlParameter("@age",SqlDbType.Int,2){Value = 888},
21          new SqlParameter("@address",SqlDbType.NVarChar,20){Value = "Jiang Su"}, 
22      };
23      command.Parameters.AddRange(parameters);  //参数也可以是一个Array数组,如果采用数组参数代码的可读性和扩展性就不是那么好了
24 
25      //当我们把参数都添加好之后,会生成一个“SqlParameterCollection”集合类型,相当于参数的集合
26      //那么我们就可以对这些参数进行修改和移除了
27      //说穿了“SqlParameterCollection”内部其实是一个List<SqlParameter>的集合,只是它里面的复杂度比较高,考虑的很全面
28      command.Parameters[0].Value = "hot girl";
29      command.Parameters[0].Size = 200;
30  }

图片 25图片 26

图片 27

            int rowCount = 0;            try            {                using (SqlConnection mSqlConnection = GetSqlConnection("SQLServerInstanceName", "DatabaseName", "", "", true))                {                    if (mSqlConnection.State == ConnectionState.Open)                    {                        Console.WriteLine("Database Connection is Open");                    }                    using (SqlCommand mSqlCommand = new SqlCommand                    {                        mSqlCommand.Connection = mSqlConnection;                        mSqlCommand.CommandText = "SELECT productId, productName, productDescription FROM product";                        mSqlCommand.CommandType = CommandType.Text;                        using (SqlDataReader mSqlDataReader = mSqlCommand.ExecuteReader                        {                            while (mSqlDataReader.Read                            {                                rowCount++;                            }                        }                    }                }            }            catch (SqlException e)            {                Console.WriteLine(e.Message);            }            catch (Exception ex)            {                Console.WriteLine(ex.Message);            }

  3.说说“SqlParameterCollection”,参数集合

View Code

     上面添加的“SqlParameter”参数都被添加到了“SqlParameterCollection”集合中去了,所以我们才能够对它进行读取和修改!

调用ExecuteReader()方法将返回的结果集存储在SqlDataReader 的对象实例mSqlDataReader中,通过对mSqlDataReader进行一系列操作,我们就可以获取到返回结果集中的详细数据了。

  4.定义适当的参数属性获取存储过程的返回值(return) → Direction = ParameterDirection.Output

注意:在使用完mSqlDataReader之后,一定记得释放资源。

    代码如下:

ExecuteScalar()方法

图片 28View Code

示例2:

 

图片 29图片 30

五丶SqlDataReader(数据流读取器)

            int totalCount = 0;            try            {                using (SqlConnection mSqlConnection = GetSqlConnection("SQLServerInstanceName", "DatabaseName", "", "", true))                {                    if (mSqlConnection.State == ConnectionState.Open)                    {                        Console.WriteLine("Database Connection is Open");                    }                    using (SqlCommand mSqlCommand = new SqlCommand                    {                        mSqlCommand.Connection = mSqlConnection;                        mSqlCommand.CommandText = string.Format("select count from webs with  where DeleteTransactionId=0x");                        mSqlCommand.CommandType = CommandType.Text;                        object result = mSqlCommand.ExecuteScalar();                        if (result != null)                        {                            totalCount = Convert.ToInt32;                        }                    }                }            }            catch (SqlException e)            {                Console.WriteLine(e.Message);            }            catch (Exception ex)            {                Console.WriteLine(ex.Message);            }

   说实话,如果单单知道怎么使用读取器,那是非常好学的,如果深入了解,它里面的知识将会非常的吸引人,那么就以我小菜的经验来说说把,各位不要见怪啊!

View Code

   1.基本用法

ExecuteScalar()方法返回结果集中第一行第一列的内容,其返回值类型为object。

图片 31View Code

3.DataReader(SqlDataReader)

   2.常用方法

DataReader用于从数据源获取只读且只进的数据集。DataReader是在查询的过程中获取数据,而不是等待查询结束。

    ①GetOrdinal:获取指定列名的列序号(索引号),使用这个方法可以把经常变动的列进行固定

DataReader通过Command对象的ExecuteReader()方法获得,我们通过演示删除DB的物理文件的操作来展示如何运用DataReader:

1 int name = dr.GetOrdinal("name"); //通过列名来获取当前列的索引号,这样如果下次你列名顺序发生变化也没有关系

代码示例如下:

    ②GetName:  获取列名,参数为指定列名的序列号,返回string

图片 32图片 33

1 string columnName = dr.GetName(name); //通过列名所处的索引号来获取列名名称 
class Program    {        private static readonly string mDefaultDatabase = "master";        static void Main(string[] args)        {            try            {                Console.WriteLine("请输入SQL Server实例名称和要删除的DB Name:");                string serverInstanceName = Console.ReadLine();                string dbName = Console.ReadLine();                bool integratedSecurity = true;                string userId = "";                string password = "";                if (string.IsNullOrEmpty(serverInstanceName) || string.IsNullOrEmpty                {                    Console.WriteLine("SQL Server实例名称和要删除的DB Name均不能为空");                }                else                {                    do                    {                        Console.WriteLine("是否使用Windows身份验证? Y:yse or N:no");                        string yes = Console.ReadLine();                        if (string.IsNullOrEmpty                        {                            Console.WriteLine("请重新选择!");                        }                        else if(yes.Equals("Yes",StringComparison.OrdinalIgnoreCase)||yes.Equals("Y", StringComparison.OrdinalIgnoreCase))                        {                            integratedSecurity = true;                            break;                        }                        else if (yes.Equals("No", StringComparison.OrdinalIgnoreCase) || yes.Equals("N", StringComparison.OrdinalIgnoreCase))                        {                            Console.WriteLine("请输入用户名和密码:");                            userId = Console.ReadLine();                            password = Console.ReadLine();                            integratedSecurity = false;                            break;                        }                        else                        {                            Console.WriteLine("请重新选择!");                        }                    }                    while (true);                    if (DeleteDbByName(serverInstanceName, dbName, userId, password, integratedSecurity))                    {                        Console.WriteLine("Delete database {0} successfully.", dbName);                    }                }            }            catch (Exception e)            {                Console.WriteLine(e.ToString;            }        }        public static bool DeleteDbByName(string serverInstanceName, string dbName, string userName, string password, bool isIntegrateSecurity)        {            bool isNull = false;            for (int i = 0; i < 5; i++)            {                try                {                    isNull = CheckDBIsNull(serverInstanceName, dbName, userName, password, isIntegrateSecurity);                    break;                }                catch (Exception e)                {                    if (i == 4)                    {                        throw new Exception("Database is null. 5 times retrying failed.");                    }                }                Thread.Sleep(2000);            }            if             {                return true;            }            string physicalDB = "";            string physicalLog = "";            GetDBPhysicalFilePath(serverInstanceName, dbName, userName, password, isIntegrateSecurity, ref physicalDB, ref physicalLog);            DeleteDBPhysicalFilePath(serverInstanceName, dbName, userName, password, isIntegrateSecurity, physicalDB, physicalLog);            return true;        }        public static SqlConnection GetSqlConnection(string serverInstance, string dbName, string userName, string password, bool integratedSecurity)        {            SqlConnection mSqlConnection = new SqlConnection();            mSqlConnection.ConnectionString = GetSqlConnectionString(serverInstance, dbName, userName, password, integratedSecurity);            mSqlConnection.Open();            return mSqlConnection;        }        public static string GetSqlConnectionString(string serverInstance, string dbName, string userName, string password, bool integratedSecurity)        {            SqlConnectionStringBuilder mSqlConnectionStringBuilder = new SqlConnectionStringBuilder();            mSqlConnectionStringBuilder.DataSource = serverInstance;            if (string.IsNullOrEmpty            {                mSqlConnectionStringBuilder.InitialCatalog = mDefaultDatabase;            }            else            {                mSqlConnectionStringBuilder.InitialCatalog = dbName;            }            if (!integratedSecurity && !string.IsNullOrEmpty && !string.IsNullOrEmpty)            {                mSqlConnectionStringBuilder.IntegratedSecurity = false;                mSqlConnectionStringBuilder.UserID = userName;                mSqlConnectionStringBuilder.Password = password;            }            else            {                mSqlConnectionStringBuilder.IntegratedSecurity = true;            }            return mSqlConnectionStringBuilder.ConnectionString;        }        public static bool CheckDBIsNull(string serverInstance, string dbName, string userName, string password, bool integratedSecurity)        {            bool dbIsNull = false;            using (SqlConnection sqlConn = GetSqlConnection(serverInstance, "", userName, password, integratedSecurity))            {                using (SqlCommand sqlCmd = new SqlCommand("master.dbo.xp_msver"))                {                    sqlCmd.Connection = sqlConn;                    string text = "USE master SELECT * FROM sysdatabases WHERE name = N'" + dbName + "'";                    sqlCmd.CommandText = text;                    sqlCmd.ExecuteNonQuery();                    if (sqlCmd.ExecuteScalar() == null)                    {                        dbIsNull = true;                    }                }            }            return dbIsNull;        }        public static void GetDBPhysicalFilePath(string serverInstance, string dbName, string userName, string password, bool integratedSecurity, ref string physicalDB, ref string physicalLog)        {            string physicalPath = string.Empty;            using (SqlConnection sqlConn = GetSqlConnection(serverInstance, "", userName, password, integratedSecurity))            {                if (GetDBStatus(sqlConn, dbName) == SQLDatabaseStatus.ONLINE)                {                    using (SqlCommand sqlCmd = new SqlCommand("master.dbo.xp_msver"))                    {                        sqlCmd.Connection = sqlConn;                        sqlCmd.CommandText = string.Format("use {0} exec sp_helpfile", dbName);                        using (SqlDataReader sqlReader = sqlCmd.ExecuteReader                        {                            while (sqlReader.Read                            {                                physicalPath = sqlReader.GetValue(2).ToString().TrimEnd("".ToCharArray;                                if (physicalPath.ToLower(CultureInfo.InvariantCulture).Contains(".mdf"))                                {                                    physicalDB = physicalPath;                                }                                else                                {                                    physicalLog = physicalPath;                                }                            }                        }                    }                }            }        }        public static void DeleteDBPhysicalFilePath(string serverInstance, string dbName, string userName, string password, bool integratedSecurity, string physicalDB, string physicalLog)        {            using (SqlConnection sqlConn = GetSqlConnection(serverInstance, "", userName, password, integratedSecurity))            {                using (SqlCommand sqlCmd = new SqlCommand("master.dbo.xp_msver"))                {                    sqlCmd.Connection = sqlConn;                    string text = string.Empty;                    sqlCmd.CommandText = string.Empty;                    sqlCmd.CommandText = GetEndDBProcessCommand;                    for (int i = 0; i < 5; i++)                    {                        try                        {                            sqlCmd.ExecuteNonQuery();                            break;                        }                        catch (Exception e)                        {                            Console.WriteLine(string.Format("Stopping all process for {0} {1} failed, {2}.", serverInstance, dbName, e.ToString;                        }                        Thread.Sleep(2000);                    }                    sqlCmd.CommandText = string.Format("drop database {0}", dbName);                    try                    {                        sqlCmd.ExecuteNonQuery();                    }                    catch (Exception e)                    {                        throw new Exception(string.Format("Failed to drop temp database {0} {1}", serverInstance, dbName));                    }                    try                    {                        if (File.Exists(physicalDB))                        {                            File.Delete(physicalDB);                        }                        if (File.Exists(physicalLog))                        {                            File.Delete(physicalLog);                        }                    }                    catch (Exception e)                    {                        Console.WriteLine(string.Format("An error occurred while deleting database {0} {1}, {2}.", serverInstance, dbName, e.ToString;                    }                }            }        }        public static string GetEndDBProcessCommand(string dbName)        {            string killpc = "declare @spid varchar n" +                "declare #spid cursor for n" +                "select spid=cast(spid as varchar from master..sysprocesses where dbid=db_id(N'" +                 dbName + "') and spid>50n" +                "open #spid n" +                "fetch next from #spid into @spid n" +                "while @@fetch_status=0 n" +                "begin n" +                "   exec('kill '+@spid) n" +                "   fetch next from #spid into @spid n" +                "end n" +                "close #spid n" +                "deallocate #spid";            return killpc;        }        public static SQLDatabaseStatus GetDBStatus(SqlConnection conn, string dbName)        {            using (SqlCommand cmd = conn.CreateCommand            {                cmd.CommandText = "SELECT DATABASEPROPERTYEX(@dbName, 'Status')";                cmd.Parameters.Add("@dbName", SqlDbType.NText).Value = dbName;                string statusString = null;                using (SqlDataReader reader = cmd.ExecuteReader                {                    if (reader.Read                    {                        statusString = reader[0].ToString();                    }                }                foreach (SQLDatabaseStatus status in Enum.GetValues(typeof(SQLDatabaseStatus)))                {                    if (status.ToString().Equals(statusString, StringComparison.OrdinalIgnoreCase))                    {                        return status;                    }                }            }            throw new Exception(string.Format("Cannot get status of database {0} on server {1}", dbName, conn.DataSource));        }        public enum SQLDatabaseStatus        {            /// <summary>            /// Database is available for query.            /// </summary>            ONLINE = 0,            /// <summary>            ///  Database was explicitly taken offline.            /// </summary>            OFFLINE = 1,            /// <summary>            /// Database is being restored.            /// </summary>            RESTORING = 2,            /// <summary>            ///  Database is recovering and not yet ready for queries.            /// </summary>            RECOVERING = 3,            /// <summary>            /// Database did not recover.            /// </summary>            SUSPECT = 4,            /// <summary>            /// Database is in an emergency, read-only state. Access is restricted to sysadmin members            /// </summary>            EMERGENCY = 5        }    }

    ③IsDBNull:判断当前读取的数据是否为Null,返回类型为Bool     

View Code

1   dr.IsDBNull(coContactID) ? "NULL" : dr.GetInt32(coContactID).ToString() //相信大家都会使用的

除此之外我们还需要注意的一点是DataReader提供了对多结果集的支持,如果返回多个结果集,则应使用DataReader的NextResult方法。该方法将按照顺序对返回的结果集进行迭代。

     ④NextResult:当查询为批处理查询时,使用这个方法去读取下一个结果集,返回值为Bool,如果存在多个结果集,则为 true;否则为 false

代码示例如下:

1 //select * from Employee;select * from County,这样的话就可以采用这种方式
2 dr.NextResult(); //记住这个要放在while(dr.Read())之后,因为读取一个数据集之后才能读取下一个数据集 

图片 34图片 35

    ⑤Read:读取数据

            try            {                using (SqlConnection mSqlConnection = GetSqlConnection("SQLServerInstanceName", "DatabaseName", "", "", true))                {                    if (mSqlConnection.State == ConnectionState.Open)                    {                        Console.WriteLine("Database Connection is Open");                    }                    using (SqlCommand mSqlCommand = mSqlConnection.CreateCommand                    {                        mSqlCommand.CommandText = "SELECT productId, productName, productDescription FROM product";                        mSqlCommand.CommandType = CommandType.Text;                        using (SqlDataReader mSqlDataReader = mSqlCommand.ExecuteReader                        {                            string outputRow = "";                            if (mSqlDataReader.HasRows)                            {                                bool mHasMoreResults = true;                                while (mHasMoreResults)                                {                                    while (mSqlDataReader.Read                                    {                                        outputRow = string.Format("{0}, {1}, {2}", mSqlDataReader.GetString(0), mSqlDataReader.GetString(1), mSqlDataReader.GetString(2));                                    }                                    mHasMoreResults = mSqlDataReader.NextResult();                                }                            }                        }                    }                }            }            catch (SqlException e)            {                Console.WriteLine(e.Message);            }            catch (Exception ex)            {                Console.WriteLine(ex.Message);            }

      读取数据最重要的方法,不说了!

View Code

  3.常用属性

4.DataAdapter(SqlDataAdapter)

    ①HasRow:判断是否包含一行或多行,也就是判断有没有数据,返回类型为Bool

DataAdapter是客户端的DataSet与数据源之间的桥梁。我们可以通过使用它来获取、插入、更新和删除数据。而根据数据方向的不同,可以使用Fill来使DataAdapter更改DataSet的数据,来保持同数据源的数据一致;使用Update可以使DataAdapter更新数据源中的数据,使数据源中的数据和DataSet保持一致。

    ②FieldCount:获取读取的列数,返回类型为Int

客户端的DataSet <—— DataAdapter(Update 方法) ——> 数据源

    ③IsClosed:判断读取的数据流是否关闭

5.数据集 DataSet

      所以灵活运用上面的属性讲增强代码的可读性和健壮性,综合示例:

数据集DataSet允许我们以关系方式表示数据。虽然在默认情况下DataSet与数据库无关,但是我们也可以在需要的时候使用针对特定数据库的功能。

图片 36View Code 

在ADO.NET中,DataSet对象主要用于支持非连接的、分布式的数据。DataSet是一种驻留于内存的数据表示,不论使用哪种数据源,它都能提供一致的关系编程模型。DataSet可以与多个不同的数据源以及XML数据配合使用,也可以用来管理应用程序自身的数据。

    Note:当 SqlDataReader 关闭后,只能调用 IsClosed 和 RecordsAffected 属性,如果调用其它方法或属性将会报错!

DataSet代表完整的数据集合,其中包括关联的表、约束和表间的关系。

  4.性能深入剖析

DataSet类的层次结构:

    读取数据的时候会有很多种写法,如 dr[0].ToString(),dr["Name"].ToString(),dr.GetString(0),dr.GetSqlString(0) 等等的读取方式的写法,如果大家去网上查资料就会很容易发现这几种写法存在着一些差异!

5.1 DataSet

    下面是读取数据性能的总结:

DataSet是对象树的根,代表数据的内存缓存,包含表以及表的关系。

图片 37

DataSet类的常用属性以及方法如下两表所示:

1     SqlDataReader读取方法:
2     1. DataReader     索引   + 基于 [序列号] → dr[0].ToString        | Index-based access
3     2. DataReader     索引   + 基于 [列名]  → dr["Name"].ToString     | 性能最差
4     3. Get            开头的 + 基于 [序列号] → dr.GetString(0)      | type-access
5     4. GetSql         开头的 + 基于 [序列号] → dr.GetSqlString(0)   | Provider-specific typed accessor
6     5. GetOrdinal()   通过列名获取这个列的序列号                      | 这个方法在提高性能上面有作用
7     6. 性能(4) --> (3) --> (1) --> (2)

构造DataSet代码:

图片 38

图片 39图片 40

     Note:所以在对数据进行读取时要有针对的使用一些性能高的方法,也不是说要追求性能,只是这是一种习惯,对于大多数读取数据库的方法使用索引来读取无疑是最快,记住一句话,“当性能没有成为问题的时候,不要过度的去优化它”,高效而又优美的使用这些方法,才是王道!

        public static DataSet BuildDataSet()        {            //创建DataSet            DataSet ds = new DataSet();            try            {                //创建DataTable,其有列和行组成                DataTable dt = new DataTable("StudentInfo");                //定义列                DataColumn[] dc = new DataColumn[7];                dc[0] = new DataColumn("StudentID", typeof(int));                dc[1] = new DataColumn("StudentName", typeof(string));                dc[2] = new DataColumn("StudentSex", typeof(string));                dc[3] = new DataColumn("StudentClass", typeof(int));                dc[4] = new DataColumn("StudentBirth", typeof(string));                dc[5] = new DataColumn("StudentPhoneNumber", typeof(string));                dc[6] = new DataColumn("StudentAddress", typeof(string));                dt.Columns.AddRange;                //为表设置主键 StudentID                dt.PrimaryKey = new DataColumn[] { dc[0] };                //为表设置完整性约束--唯一性约束 StudentName 主键的设置和唯一性约束不能相同,否则会出现重复                dt.Constraints.Add(new UniqueConstraint(dc[1]));                //设置行                dt.Rows.Add(new object[] { 101, "王国强", "男", 101, "1992年5月18日", "13990824456", "东1舍423" });                dt.Rows.Add(new object[] { 102, "张丽华", "女", 101, "1991年10月25日", "13846725530", "东2舍301" });                dt.Rows.Add(new object[] { 103, "孙美美", "女", 102, "1992年3月23日", "13456890034", "东2舍402" });                //主键具有唯一性,因此StudentID不能相同,否则会报错                //dt.Rows.Add(new object[] { 101, "孙美美", "女", 102, "1992年3月23日", "13456890034", "东2舍402" });                //StudentName设置了唯一性约束,因此不能出现重复值,否则报错                //dt.Rows.Add(new object[] { 104, "孙美美", "女", 102, "1992年3月23日", "13456890034", "东2舍402" });                ds.Tables.Add;            }            catch (Exception ex)            {                Console.WriteLine(ex.Message);            }            return ds;        }

    推荐文章:SqlDataReader 提前终止的性能问题

View Code

    PS:我这里的总结其实是以前在园子看到一个人写的,找了半个小时都没找到,如果有人看到过,发个链接给我,我补上!

5.2 DataTable

  5.SqlDataReader和DataSet的讨论

DataTable代表内存中的数据表。如果要在代码中创建DataTable,则首先需要使用DataColumnCollection添加列Column来定义表的结构。而在表中添加行row,需要使用DataTable的NewRow方法来创建新的DataRow对象。除此之外,DataTable还包含一个Constraint对象的集合,用来确保数据的完整性。

    推荐文章:谈谈Asp.net网站优化一:SqlDataReader和DataSet的选择

DataTable的常用属性以及方法如下两表所示:

 

5.3 DataRow

六丶SqlTransaction(事务)

行和列用于在DataTable中存储数据。DataRow对象提供了选定列的字典式的访问方式,其存储各列的值。同时,行也可以存储从数据库中获取的数据,也可以用于插入、删除以及更新DataTable中的值。

   1.代码中的事务    

5.4 DataColumn

    现在代码中基本使用存储过程来控制事务的处理,通过代码进行控制事务也是我们学习ADO.NET的任务之一!

DataColumn用于定义表中的列。DataColumn的DataType属性可以用来定义列的数据类型。

    事务是在连接对象之后创建,并把它跟命令对象进行关联,使用try.....Catch捕获异常,然后调用RollBack方法回滚事务!

AllowDBNull、Unqiue以及ReadOnly属性可以对数据项添加约束,并对数据进行更新,有助于确保数据的完整性。

    Commit:提交

同时,其的AutoIncrement、AutoIncrementSeed以及AutoIncrementStep属性可以来控制值的自动生成。

    RollBack:回滚

最后,我们可以通过DataColumn中的Expression属性来计算列中的值或者来创建聚合列。

图片 41View Code

创建DataColumn和DataRow的示例如下所示:

  2.事务中的命名存储点      

            DataSet ds = new DataSet();            DataTable dt = new DataTable("Students");            DataColumn dc1 = new DataColumn("StudentName", typeof(string));            DataColumn dc2 = new DataColumn("StudentID", typeof(int));            dt.Columns.Add;            dt.Columns.Add;            DataRow dr1 = dt.NewRow();            dr1["StudentName"] = "雄霸";            dr1["StudentID"] = 101;            dt.Rows.Add;            DataRow dr2 = dt.NewRow();            dr2[dc1] = "聂风";            dr2[dc2] = 102;            dt.Rows.Add;            DataRow dr3 = dt.NewRow();            dr3[0] = "步惊云";            dr3[1] = 103;            dt.Rows.Add;            ds.Tables.Add;

    一旦你定义了命名存储点,只能回滚命名存储点之后的操作,这是要是情况而使用!

5.5 DataView

    这种情况是当你调用RollBack方法并重载一个命名存储点的参数,如下代码所示:

同数据库一样,DataView用于在DataTable上创建视图,允许视图中的数据作为DataTable中数据的子集,同时,还可以进行不同方式的排序。

图片 42

5.6 从数据库中读取数据

 1     using (SqlConnection conn = new SqlConnection(str))
 2     {
 3          conn.Open();
 4          SqlTransaction transaction = conn.BeginTransaction();
 5          SqlCommand cmd = conn.CreateCommand();
 6          cmd.CommandText = "";
 7          cmd.Transaction = transaction;
 8          //使用命名存储点
 9          transaction.Save("this is point");  //定义命名存储点,使用Save方法先保存存储点,定义回滚数据的开始位置
10                 
11          //这边是你要回滚的操作代码,TO DO...
12 
13          //把从命名存储点到这里的操作进行回滚
14          transaction.Rollback("this is point");  //回滚命名存储点              
15      }

数据适配器DataAdapter 用来从数据库中读取数据,并将数据填充到DataSet以及DataTable中;同时,DataSet和DataTable还可以将数据写回到数据库中,完成数据库中数据的更新。

图片 43

使用DataAdapter获取数据库数据的流程:连接数据库 —> 获取数据库中的数据 —> 使用DataAdapter填充到DataSet和DataTable中。

  3.SQL语句中的事务(SQL Server中的事务其实很复杂的)

代码示例如下所示:

图片 44

            try            {                DataSet ds = new DataSet();                //连接数据库获取数据,填充到DataSet中                using (SqlConnection sqlConnection = new SqlConnection(@"Data Source =.;Initial Catalog = StudentInfomation;Integrated Security = True"))                {                    using (SqlCommand sqlCommand = new SqlCommand("select * from Students", sqlConnection))                    {                        using (SqlDataAdapter adapter = new SqlDataAdapter(sqlCommand))                        {                            adapter.Fill(ds, "Students");                            adapter.FillSchema(ds, SchemaType.Source, "Students");                        }                    }                }            }            catch (Exception ex)            {                Console.WriteLine(ex.Message);            }
1 BEGIN TRANSACTION
2 
3     --你需要执行的更新,删除,插入的语句
4     
5 IF(@@ERROR > 0) //这是系统变量,存储你在执行更新,删除,插入操作时发生错误的记录编号
6     ROLLBACK
7 ELSE
8     COMMIT

5.7 DataSet数据类型

图片 45

DataSet位于命名空间System.Data中,且与数据库无关。我们将数据从数据库加载到DataSet中后,数据源便会脱离,无法通过DataSet进行操作。

     推荐文章:浅谈SQL SERVER中事务的ACID

FillSchema:如果将ReturnProviderSpecificTypes设置为true,则就不能再使用FillSchema。

          深入sql server中的事务

  4.说说“TransactionScope”,让事务更加的简单 

图片 46

 1 using (TransactionScope transactionScope = new TransactionScope())
 2 {
 3     try
 4     {
 5         using (SqlConnection connection = new SqlConnection())
 6         {
 7             // TO DO
 8             //提交事务,如果有异常,他会自动回滚的
 9             transactionScope.Complete();
10         }
11     }
12     catch (Exception)
13     {
14         //捕获异常
15         throw;
16     }
17 }

图片 47

     推荐文章:C#综合揭秘——细说事务

 

七丶SqlDataAdapter(数据适配器)

  1.构造函数 

图片 48

1 四个重载:    
2   1. 无参
3   2. SqlDataAdapter(SqlCommand)  → 执行命令对象实例
4   3. SqlDataAdapter(String, SqlConnection) → ①只能指定查询语句 ②连接对象实例
5   4. SqlDataAdapter(String, ConnectionString) → 用 SelectCommand 和一个连接字符串初始化 SqlDataAdapter 类的一个新实例
6   Note:第四个重载就把连接对象和命令对象都包含进去了!

图片 49

  2.填充数据(Fill)

     最简单的填充数据 

图片 50

1 DataSet dataSet = new DataSet();
2 using (SqlConnection conn = new SqlConnection(""))
3 {
4     conn.Open();
5     SqlCommand command = conn.CreateCommand();
6     command.CommandText = "select name,age,address from MyInformation";
7     SqlDataAdapter dataAdapter = new SqlDataAdapter(command);
8     dataAdapter.Fill(dataSet);  //填充数据
9 }

图片 51

   3.使用“SqlCommandBuilder”对数据进行增删改查

     ①添加数据

图片 52

 1  using (SqlConnection conn = new SqlConnection(ConnectionString()))
 2  {
 3      conn.Open();
 4      //构建查询语句,也可以指定SqlCommand,其中变换的方法有很多
 5      SqlDataAdapter da = new SqlDataAdapter("select LastName,FirstName from dbo.Employees", conn);
 6      DataSet ds = new DataSet();
 7      da.Fill(ds);
 8      //这句话很重要,它会把你在DataSet增加的数据转化为SQL语句用来更新数据库
 9      SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(da);
10      //添加行,实例化一个行对象,注意是用NewRow来创建行
11      DataRow row = ds.Tables[0].NewRow();
12      row[0] = "Yang";
13      row[1] = "鬼头";
14      ds.Tables[0].Rows.Add(row);  //添加到表中
15      da.Update(ds);             //把DataSet中表和数据库进行对比,更新
16  }

图片 53

     ②修改数据

图片 54

 1 using (SqlConnection conn = new SqlConnection(""))
 2 {
 3     SqlDataAdapter da = new SqlDataAdapter("SQL语句或你自己定义的命令对象", conn);
 4     DataSet ds = new DataSet();
 5     da.Fill(ds);
 6     //很重要的一句话
 7     SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(da);
 8     ds.Tables[0].Rows[12][1] = ""; //修改数据
 9     da.Update(ds);
10     //调用Update方法其中隐式的调用了AcceptChanges方法,更新数据集中的数据
11     //如果你继续使用这个数据集而没有调用这个方法,在后面的使用会出现异常
12     ds.AcceptChanges();  //这句话可以不写的
13 }

图片 55

     ③删除数据

图片 56

 1  using (SqlConnection conn = new SqlConnection(""))
 2  {
 3      SqlDataAdapter da = new SqlDataAdapter("SQL语句或你自己定义的命令对象", conn);
 4      DataSet ds = new DataSet();
 5      da.Fill(ds);
 6      SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(da);
 7      //删除数据
 8      ds.Tables[0].Rows[12].Delete();
 9      da.Update(ds);  //这边会隐式调用DataTable的AcceptChanges方法
10  }

图片 57

     Note(很重要的注意点): 值得注意的是Update方法已经隐式帮我调用了AcceptChanges,不比担心状态为改变删除数据会报错,微软已经帮我们都做好了,其实背后就是 做的Table.AcceptChanges()这件事,如果在一般的DataTable中会怎么样,提交自上次调用 AcceptChanges 以来对该行进行的所有更改,在调用这个方法之后,表中所有更改将会提交,所有行状态(RowState)状态都将变为Unchanged,在DataSet中我将会说到这些内容!

  4.关于“SqlDataAdapter”中Fill方法的一些讨论

    简单的写一下,MSDN上都有的,查一下就知道了!

1 ★指定填充数据的数量,如:
2 //从第五行到第十行数据填充DataSet   
3 //上面的定义错了
4 //应该是从第六行开始,后面的十条记录
5 da.Fill(ds,5,10,”MyTable”) 

  

八丶DataSet,DataTable,DataRow,DataColumn

  表示数据存放在缓存中,DataSet里面可以包含多个DataTable,DataTable中有多个DataColumn和多个 DataRow,包括对各种对DataTable的操作,以及对列和行的操作,在进行DataSet,DataTable进行操作的时候,应该先判断它们 是否为Null,这是最基本的!

  1.DataTable,DataRow,DataColumn

    ①创建自己的DataTable 

图片 58View Code

    ②使用对象集合初始化器简化代码,以及使用“DataColumnCollection”和“DataRowCollection”来操作已添加的行和列

    构造函数的访问修饰符为Internal,通过这两个集合可以对Column和Row进行“增,删,改,查”,详细见MSDN,如Remove,Add,RemoveAt etc!

图片 59

 1 dt.Columns.Add(new DataColumn("Age", typeof(Int32)));
 2 dt.Columns.Add(new DataColumn()
 3 {
 4     ColumnName = "Address",
 5     DataType = typeof(string),
 6     DefaultValue = "江苏海安"
 7 });
 8 //我们这边使用Add的方法的第二个重载
 9 dt.Rows.Add(new object[] {"11", 44, "222", "yang cao gui"});
10 //我们也可以对添加好的行和列进行读取和修改
11 dt.Columns[0].ColumnName = "wang wei";
12 dt.Rows[0]["wang wei"] = "我把这行这列的值修改了,哈哈";

图片 60

    ③使用表达树快速构建自己的列,详细的也可以查MSDN

图片 61View Code

  2.DataRowState(行状态),DataRowVersion(行版本)

    ①DataRowState(行状态)是“DataRow”中一个很重要的状态,主要有五个方面:

1     Added          → 添加
2     Deleted        → 删除
3     Detached       → 分离
4     Modified       → 修改
5     Unchanged      → 为改变

     图片 62

     Note:如果实例化一个行,但没有加入到任何一个表中,那么它的状态永远是Detached,不存在Add,Modified之分,这个是要注意的!

    ②DataRowVersion(行版本),有四个版本状态,如下:

1     Current     → 最近的行,主要针对Deleted操作之前的行,行状态的Deleted
2     Default     → 行的默认状态
3     Original    → 行的原始值 Added,Modified,Unchanged    
4     Proposed    → 行的建议值 

     图片 63

    PS:如果想理解它们,应该要写一些示例代码来模拟它们,这样就能很好的熟悉它们了!

    强烈推荐这篇文章:→ 深入.NET DataTable(写的很仔细,不错,一定要看的),还有这篇 → 深入.NET DataTable(补遗)

  3.DataSet,DataTable

    比较重要的方法:Select,Merge,Copy,Clone,GetChanges等等

    关于GetChanges方法:获取数据改变的地方,它所获取的是你上次调用AcceptChanges方法之后修改数据的信息,这点要注意了! 

  4.下面是对DataSet和DataTable讲的比较好的文章收集  

    DataTable.Select使用小心得

    DataTable 深入解析数据源绑定原理之高级篇

    比较两个DataTable数据(结构相同)——5万条数据仅需几秒

  5.关于“DataRelation”和“DataView”的知识也很重要 

    DataView → 表示用于排序、筛选、搜索、编辑和导航的 DataTable的可绑定数据的自定义视图,看文章:DataSet,DataTable,DataView

    DataRelation → 表示两个 DataTable 对象之间的父/子关系,看文章:DataRelation(DataSet中父子表)的一个示例

 

九丶封装数据库操作类(这才是精华) 

     只有充分理解了上面的知识,才能更好的封装,才能写出健壮的面向对象数据库操作类库,因本人知识有限,简单的封装还可以,但是不足以见人,所以收集了了一些好文章,供我们来学习:

    1.SqlHelper- -高悬的双刃剑(到底好用么~~) (提炼更加健壮的代码)

    2.我的DbHelper数据操作类(自定义操作类库)

    3.JSM SqlHelper 2.0 源码下载(封装的更细啦,有机会研究研究)

    4.微软原版SQLHelper类(代码太多,有很多我们会用不到,还有重载的也太多了吧!)

  好了就这么多了,想简单也很简单,想复杂登天还难,哈哈,还是看个人的选择把,园子里面这方面的文章也有很多,一搜一大堆,好好研究下就ok了!

结束:写了一个星期,终于搞完了,肯定还有很多地方没有涉及到的,大家多多指点...

本文由9159.com发布于编程,转载请注明出处:1.连接字符串,我们可以高效的完成客户端同数据

关键词: