在非串連模式下,主要討論以下對象: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被重載的方法有很多,具體可以查看:http://msdn.microsoft.com/zh-cn/library/system.data.sqlclient.sqldataadapter.fill.aspx
3.3 DataAdapter的FillSchema方法
SqlDataAdapter 類提供 Fill 和 FillSchema 兩種方法,這對於載入這些資料很關鍵。這兩種方法均可將資訊載入到 DataSet 中。Fill 載入資料本身,而 FillSchema 載入有關特定表的所有可用的中繼資料(如列名、主鍵和約束)。處理資料載入的正確方式是先運行 FillSchema,後運行 Fill。例如:
daAuthors.FillSchema(dsPubs,SchemaType.Source, "Authors");
daAuthors.Fill(dsPubs,"Authors");
具體的參照以下幾篇文章:
http://msdn.microsoft.com/zh-cn/library/49z48hxc.aspx
http://support.microsoft.com/kb/314145/zh-cn
例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