通过ADO.NET技术,我们可以高效的完成客户端同数据库之间的数据访问操作,便于我们在客户端程序简便高效的访问以及获取数据库中的有用数据,同时也可以对数据库中的数据进行更新,即可以完成客户端与数据库之间的双向操作。
本文简单介绍如何在客户端程序中利用ADO.NET 技术来访问以及使用数据库中的数据。
ADO.NET对象模型的最主要的4个组成部分分别是:Connection(SQLConnection)、Command(SQLCommand)、DataReader(SQLDataReader),DataAdapter(SQLDataAdapter)。
下面我们将详细介绍这四种对象的基本用法和其常用的属性、方法以及如何利用它们来完成对数据库的访问操作。
1、Connection(SQLConnection)
Connection对象位于最顶层,是所有数据访问请求的关口。简单来说,我们访问数据库中的数据的一般流程为:连接目标数据库-->访问执行命令(如结构化查询语言命令)-->返回命令执行结果并进行处理-->关闭连接,而Connection对象就用于流程的第一步:
连接目标数据库(即连接数据源)
我们先看一下以下简单实例:
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(); } } }
首先,为了能够使用SQLConnection类,我们首先需要引用命名空间System.Data.SqlClient(using System.Data.SqlClient);接着创建SQLConnection类型的实例对象
mSqlConnection,为其属性ConnectionString赋值连接字符串;然后调用Open()方法,这就完成了数据库的连接操作;最后记得在完成访问数据操作之后,调用Close()方法,关闭连接。
Connection对象具有多个属性以及方法,下面介绍最基础常用的属性以及方法:
常用属性:
ConnectionString:获取或设置用来打开SQLServer数据库的连接字符串
ConnectionTimeout:获取等待时间,即终止尝试连接操作或者返回错误信息之前的等待时间。
DataSource:获取要连接的SQL Server实例名称。
Database:获取数据库的名称。
常用方法:
Open():使用COnnectionString中指定的属性设置数据库连接。
Close():关闭数据库连接。
我们在连接字符串中可以看到设置了Data Source、InitialCatalog以及Integrated Security三个值:Data Source表示要连接的SQL Server实例名称;Initial Catalog表示要访问的数据库名称;
Integrated Security表示所采用的安全验证方式。
Integrated Security设置为SSPI或者true,则表示采用Windows身份验证;否则表示采用SQL Server身份验证,此时就需要在连接字符串中设置User ID和Password
连接字符串的设置
连接字符串既可以在ConnectionString属性中设置,也可以在创建SqlConnection实例对象时设置,还可以在配置文件中设置:
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); } } }
配置文件如下:
<?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=4.5"/> </startup> </configuration>
注意:获取配置文件中的连接字符串时首先需要引用System.Configuration(using System.Configuration
资源释放以及异常处理
数据库的连接操作时十分占用资源的,在使用完成之后一定要关闭连接,释放资源。一般调用Close()方法关闭连接,释放资源。但有时我们会忘记调用Close()方法,这就导致了资源的浪费。为了避免这种情况的发生,我们可以使用using来完成资源的释放。而对于异常处理,我们可以使用try{...}catch(...){...}操作,示例代码如下所示:
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); }
对SQLConnection实例对象mSqlConnection相关操作的进一步封装
我们可以将对mSqlConnection 的相关操作进一步提取封装到一个方法中,这样有利于代码的重用,示例如下所示:
注意:下面的代码中我们将使用SQLConnectionStringBuilder对象来创建连接字符串
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(username) && !string.IsNullOrEmpty(password)) { mSqlConnectionStringBuilder.IntegratedSecurity=false; mSqlConnectionStringBuilder.UserID=username; mSqlConnectionStringBuilder.Password=password;} else{ mSqlConnectionStringBuilder.IntegratedSecurity=true; } return mSqlConnectionStringBuilder.ConnectionString; } }}
2、Command(SQLCommand)
当成功连接到数据库之后,接下来我们就要进行数据的访问操作了,比如对数据源的查询操作等,这时就需要使用Command对象了。
SQLCommand类最基本常用的属性和方法如下所示(其他的不在这里列举,读者可自行查询)
方法:
ExecuteNonQuery():用于执行SQL语句,该方法用于不需要返回任何记录的情况(例如,INSERT,DELETE或UPDATE查询)
ExecuteReader():用于执行SQL语句并返回一组数据。
ExecuteScalar():用于执行查询,并返回查询所返回的结果集中第一行第一列的内容,其他内容将被忽略。
ExecuteXmlReader():以XmlReader 形式返回结果集。
属性:
CommandText:设置对数据源执行的文本命令
CommandTimeout:等待时间
CommandType:对CommandText属性的解释(枚举,其中包括StoredProcedure、TableDirect和Text)
Connection:数据库连接。
Parameters:Parameter对象的集合
ExecuteReader()方法
示例1:
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); }
调用ExecuteReader()方法将返回的结构集存储在SqlDataReader的对象实例mSqlDataReader中,通过对mSqlDataReader进行一系列操作,我们就可以获取到返回结果集中的详细数据了。
注意:在使用完mSqlDataReader之后,一定记得释放资源
ExecuteScalar()方法
示例2:
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 (nolock) where DeleteTransactionId=0x"); mSqlCommand.COmmndType=CommandType.Text; object result=mSqlCommand.ExecuteScalar(); if(result !=null) { totalCount=Convert.ToInt32(result); } } } } catch(SqlException e) { Console.WriteLine(e.Message); } catch(Exception ex) { Console.WriteLine(ex.Message); }
ExecuteScalar()方法返回结果集中第一行第一列的内容,其返回值类型为object
3、DataReader(SQLDataReader)
DataReader用于从数据源获取只读且只进的数据集。DataReader是在查询的过程中获取数据,而不是等待查询结束。
DataReader通过Command对象的ExecuteReader() 方法获得,我们通过演示删除DB的物理文件的操作来展示如何运用DataReader:
代码示例如下:
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(dbName)) { Console.WriteLine("SQL Server实例名称和要删除的DB Name均不能为空"); } else { do { Console.WriteLine("是否使用Windows身份验证? Y:yse or N:no"); string yes = Console.ReadLine(); if (string.IsNullOrEmpty(yes)) { 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 (isNull) { 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(dbName)) { mSqlConnectionStringBuilder.InitialCatalog = mDefaultDatabase; } else { mSqlConnectionStringBuilder.InitialCatalog = dbName; } if (!integratedSecurity && !string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password)) { 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(dbName); 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(20) " + "declare #spid cursor for " + "select spid=cast(spid as varchar(20)) from master..sysprocesses where dbid=db_id(N'" + dbName + "') and spid>50 " + "open #spid " + "fetch next from #spid into @spid " + "while @@fetch_status=0 " + "begin " + " exec('kill '+@spid) " + " fetch next from #spid into @spid " + "end " + "close #spid " + "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 } }
除此之外我们还需要注意的一点是DataReader提供了对多结果集的支持,如果返回多个结果集,则应使用DataReader的NextResult方法。该方法将按照顺序对返回的结果集进行迭代,
代码示例如下:
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); }
4.DataAdapter(SqlDataAdapter)
DataAdapter是客户端的DataSet与数据源之间的桥梁。我们可以通过使用它来获取、插入、更新和删除数据。而根据数据方向的不同,可以使用Fill来使DataAdapter更改DataSet的数据,来保持同数据源的数据一致;使用Update可以使DataAdapter更新数据源中的数据,使数据源中的数据和DataSet保持一致。
客户端的DataSet <——(Fill方法) DataAdapter(Update 方法) ——> 数据源
5.数据集 DataSet
数据集DataSet允许我们以关系方式表示数据。虽然在默认情况下DataSet与数据库无关,但是我们也可以在需要的时候使用针对特定数据库的功能。
在ADO.NET中,DataSet对象主要用于支持非连接的、分布式的数据。DataSet是一种驻留于内存的数据表示,不论使用哪种数据源,它都能提供一致的关系编程模型。DataSet可以与多个不同的数据源以及XML数据配合使用,也可以用来管理应用程序自身的数据。
DataSet代表完整的数据集合,其中包括关联的表、约束和表间的关系。
DataSet类的层次结构:
5.1 DataSet
DataSet是对象树的根,代表数据的内存缓存,包含表以及表的关系。
DataSet类的常用属性以及方法如下两表所示:
构造DataSet代码:
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(dc); //为表设置主键 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(dt); } catch (Exception ex) { Console.WriteLine(ex.Message); } return ds; }
5.2 DataTable
DataTable代表内存中的数据表。如果要在代码中创建DataTable,则首先需要使用DataColumnCollection添加列Column来定义表的结构。而在表中添加行row,需要使用DataTable的NewRow方法来创建新的DataRow对象。除此之外,DataTable还包含一个Constraint对象的集合,用来确保数据的完整性。
DataTable的常用属性以及方法如下两表所示:
5.3 DataRow
行和列用于在DataTable中存储数据。DataRow对象提供了选定列的字典式的访问方式,其存储各列的值。同时,行也可以存储从数据库中获取的数据,也可以用于插入、删除以及更新DataTable中的值。
5.4 DataColumn
DataColumn用于定义表中的列。DataColumn的DataType属性可以用来定义列的数据类型。
AllowDBNull、Unqiue以及ReadOnly属性可以对数据项添加约束,并对数据进行更新,有助于确保数据的完整性。
同时,其的AutoIncrement、AutoIncrementSeed以及AutoIncrementStep属性可以来控制值的自动生成。
最后,我们可以通过DataColumn中的Expression属性来计算列中的值或者来创建聚合列。
创建DataColumn和DataRow的示例如下所示:
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(dc1); dt.Columns.Add(dc2); DataRow dr1 = dt.NewRow(); dr1["StudentName"] = "雄霸"; dr1["StudentID"] = 101; dt.Rows.Add(dr1); DataRow dr2 = dt.NewRow(); dr2[dc1] = "聂风"; dr2[dc2] = 102; dt.Rows.Add(dr2); DataRow dr3 = dt.NewRow(); dr3[0] = "步惊云"; dr3[1] = 103; dt.Rows.Add(dr3); ds.Tables.Add(dt);
5.5 DataView
同数据库一样,DataView用于在DataTable上创建视图,允许视图中的数据作为DataTable中数据的子集,同时,还可以进行不同方式的排序。
5.6 从数据库中读取数据
数据适配器DataAdapter 用来从数据库中读取数据,并将数据填充到DataSet以及DataTable中;同时,DataSet和DataTable还可以将数据写回到数据库中,完成数据库中数据的更新。
使用DataAdapter获取数据库数据的流程:连接数据库(连接数据源) —> 获取数据库中的数据 —> 使用DataAdapter填充到DataSet和DataTable中。
代码示例如下所示:
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); }
5.7 DataSet数据类型
DataSet位于命名空间System.Data中,且与数据库无关。我们将数据从数据库加载到DataSet中后,数据源便会脱离,无法通过DataSet进行操作。
FillSchema:如果将ReturnProviderSpecificTypes设置为true,则就不能再使用FillSchema。