原文:
在非连接模式下,主要讨论以下对象:DataAdapter。 DataAdpater的作用是在物理存储模式的数据和内存之间进行数据传递。DataTable是用在内存中表示数据库表。DataSet是内存中表示数据库(表、表关系的集合)。DataView是用于在内存中表示数据库视图。 DataAdapter对象在后台使用DataReader对象从数据库中获取数据;DataView对象来对数据进行过滤和排序;DataTable对象可以用来跟踪数据记录的改变情况,并决定是否接受或者拒绝这些改变。
1.DataAdapter对象
DataAdapter对象在物理数据库和内存数据表之间起桥梁的作用。一般用DataAdapter对象从数据库获取数据并装入DataTable对象中,也通过DataAdapter对象将DataTable对象中数据的修改写回到物理数据库。 例1: 一个简单的DataAdapter对象的使用 === App_Code\DawnDataObject.cs ===
Code public class Movie_Disconnect{ private static readonly string _connectionstring; static Movie_Disconnect() { _connectionstring = WebConfigurationManager.ConnectionStrings["DawnEnterpriseDBConnectionString"]. ConnectionString.ToString(); } public DataTable GetAll() { // 初始化DataAdapter SqlDataAdapter dad = new SqlDataAdapter("Select Id,Title,Director from Movies", _connectionstring); // 初始化Table DataTable dt = new DataTable(); dad.Fill(dt); return dt; }} === showMovies.aspx
Code <asp:GridView ID="GridView1" runat="server" DataSourceID="ObjectDataSource1"></asp:GridView><asp:ObjectDataSource ID="ObjectDataSource1" TypeName="DawnDataObject.Movie_Disconnect" SelectMethod="GetAll" runat="server"></asp:ObjectDataSource>
2.DataAdapter的构造
在例1中,我们看到了如何构造一个SqlDataAdapter对象,并且使用Fill方法把数据表填到一个DataTable中。它看起来是像下面这样子的:
SqlDataAdapter dad = new SqlDataAdapter( " Select Id,Title,Director from Movies " , _connectionstring);DataTable dt = new DataTable();dad.Fill(dt); 在以上的例子中,看不到SqlConnection,SqlCommand对象的出象,其实,它们还是隐含存在的,这些对象被SqlDataAdapter对象调用了而已,就连SqlConnection对象的Open()方法的调用也由SqlDataAdapter对象来代劳了。 如果要显式使用SqlConnection,SqlCommand对象,可以像以下代码这样: 例2: SqlAdapter对象的另外构造方法
public DataTable GetAll(){ DataTable dt = new DataTable(); using (SqlConnection conn = new SqlConnection(_connectionstring)) { SqlCommand command = new SqlCommand( " Select Id,Title,Director from Movies " , conn); SqlDataAdapter dad = new SqlDataAdapter(command); // 初始化Table dad.Fill(dt); } return dt;} 以上,可以看出,SqlDataAdapter构造函数可以传入一个SqlCommand对象。在ADO.Net中SqlDataAdapter构造函数可以使用以下几种方法进行构造 ● SqlDataAdapter(): 无参数,构造后,可以给SqlDataAdapter对象的SelectCommand属性分配一个SqlCommand对象。 作为补充,SqlDataAdapter还有UpdateCommand、DeleteCommand、InsertCommand属性,这些属性在后面会提到。 ● SqlDataAdapter(string commandText, SqlConnection connection): 第一个参数为T-SQL语句,第二个参数为一个SqlConnection对象。 使用这个构造函数时,不需要显式声明SqlCommand对象。 ● SqlDataAdapter(string commandText, string connectionString): 例1使用的方法,不需要显式声明SqlConnection与SqlCommand对象 ● SqlDataAdapter(SqlCommand command): 例2使用的方法。
3. SqlDataAdapter的Fill/FillSchema方法
DataAdapter对象的Fill方法,该方法不止可以传入DataTable作为参数,也可以传入DataSet作为参数。 DataAdapter对象的FillSchema方法,可以向DataSet/DataTable参数添加现有的数据库约束。 3.1 赋值到DataSet 因为DataSet是DataTable的集合,所以可以Fill多张表到DataSet对象中。 例3: Fill多张数据表到DataSet对象
private void buttonFillData_Click( object sender, EventArgs e){ DataSet userData = new DataSet(); using (SqlConnection testConnection = new SqlConnection(connectionString)) { SqlCommand testCommand = testConnection.CreateCommand(); testCommand.CommandText = " Select FirstName, LastName from userTable; Select PermissionType from PermissionsTable " ; SqlDataAdapter dataAdapter = new SqlDataAdapter(testCommand); dataAdapter.Fill(userData); } // testConnection.Dispose called automatically. } 3.2 Fill方法的重载 默认的,当调用SqlDataAdapter.Fill(DataSet)时,并没有指定Table名,所以,要想取得DataSet中的DataTable对象,需要使用Index序号。 也可以指定当Fill进DataSet时,相应表的TableName属性,当需要指定TableName属性时,调用以下Fill方法: public int Fill(DataSet dataSet, string srcTable); 以下的例子是它们之间的区别: 例4: 调用Fill方法填充到DataSet时,指定TableName属性
protected void Page_Load( object sender, EventArgs e) { if ( ! IsPostBack) { string _connectionstring = WebConfigurationManager.ConnectionStrings[ " DawnEnterpriseDBConnectionString " ]. ConnectionString.ToString(); DataSet ds = new DataSet(); using (SqlConnection conn = new SqlConnection(_connectionstring)) { SqlCommand command = new SqlCommand( " Select Id,Title,Director from Movies " , conn); SqlDataAdapter dad = new SqlDataAdapter(command); dad.Fill(ds, " Movies " ); // 调用Fill方法时,使用TableName dad.SelectCommand = new SqlCommand( " select Id,name from MovieCategories " , conn); dad.Fill(ds); // 为使用TableName GridView1.DataSource = ds.Tables[ " Movies " ]; // 使用TableName进行指定 GridView1.DataBind(); GridView2.DataSource = ds.Tables[ 1 ]; // 使用inde进行指定 GridView2.DataBind(); } } } Fill被重载的方法有很多,具体可以查看: 3.3 DataAdapter的FillSchema方法 SqlDataAdapter 类提供 Fill 和 FillSchema 两种方法,这对于加载这些数据很关键。这两种方法均可将信息加载到 DataSet 中。Fill 加载数据本身,而 FillSchema 加载有关特定表的所有可用的元数据(如列名、主键和约束)。处理数据加载的正确方式是先运行 FillSchema,后运行 Fill。例如: daAuthors.FillSchema(dsPubs,SchemaType.Source, "Authors"); daAuthors.Fill(dsPubs,"Authors"); 具体的参照以下几篇文章:
例5:调用FillSchema方法: //一般先用FillSchema来填入详细的元数据信息,再用Fill来填充数据,例如: sqlDataAdapter1.FillSchema(dataSet1,SchemaType.Source, " authors " );sqlDataAdapter1.Fill(dataSet1, " authors " );DataColumn[] colArr;colArr = dataSet1.Tables[ " authors " ].PrimaryKey;MessageBox.Show( " Column Count: " + colArr.Length.ToString()); for ( int i = 0 ; i < colArr.Length; i ++ ){ MessageBox.Show(colArr[i].ColumnName + " " + colArr[i].DataType.ToString());} 在上例中,如果不调用FillSchema, 缺省情况下不会填如PrimaryKey信息。 另外,DataAdapter还有一个MissingSchemaAction属性,该属性可以接受以下Enum值: ● Add---在添加新行时向DataTable中添加必须的附加列(默认值) ● AddWithKey---在添加新行时向DataTAble中添加所有必须的列。 ● Error---在添加新行时,如果此行不匹配现在的DataTable,就引发一个错误。 ● Ignore---在添加新行时,如果此行中包含DataTable中没有的列,那么忽略多余的列。 ds.MissingSchemaAction = MissingSchemaAction.AddWithkey