DataAdapter & DataSet 使用小結

ForTechnology發表於2011-08-05
DataAdapter & DataSet 使用小結 收藏
 
一、 Data Adapter的主要作用
Adapter是database與Dataset或DataTable之間的介面,它從資料庫中get資料並填充至Dataset或Data table,這樣就可以實現離線處理資料的能力。
一旦adapter物件將資料填充或提交完畢,它和所填充的Dataset物件就沒有了任何聯絡。
二、Data Adapter重要屬性或方法
(1)    Child Commands:這裡主要包括4個commands物件
SelectCommand, UpdateCommand, InsertCommand, and DeleteCommand
(2)    Table Mappings Collection
這裡需要了解一下填充機制,adapter預設向Dataset填充時,table Name依次是Table\Table1\Table2…。我們可以使用Table Mappings屬性來設定我們需要的Table Name。一種方法是在fill的時候 指定,這種比較常見,還有一種是使用如下的程式碼去實現:
DbDataAdapter da = factory.CreateDataAdapter();
             da.SelectCommand = cmd;
             DataTableMapping tableMapping = da.TableMappings.Add("Table", "OrdersMapping");
             DataColumnMapping colMapping;
             colMapping = tableMapping.ColumnMappings.Add("OrderID", "訂單號");
colMapping = tableMapping.ColumnMappings.Add("CustomerID", "客戶名");
再向dataset填充的時候,表名就是 OrdersMapping,OrderID也被對映成訂單號。這種應用在繫結Datagridview的時候可以應用。
使用這個功能時還要注意設定MissingMappingAction屬性,不同的列舉值代表不同的處理方式。具體如下:
By default, this property is set to Passthrough. When the MissingMappingAction property is set to this value, the DataAdapter maps missing columns in your results to columns with the same name in your DataSet. Setting this property to Ignore tells the DataAdapter to ignore columns that don’t appear in the mappings collection. You can also set the MissingMappingAction property to Error, which will cause the DataAdapter to throw an exception if it detects a column in the results of your query that does not exist in the mappings collection.
(3)    使用data adapter的page功能
DataAdapter.Fill(DataSet, 0, 20, "Products")
注意:這時候即使查詢出的記錄有很多,也只有20條記錄被get到本地。
(4)    與資料庫連線的管理
如果在呼叫fill方法之前connection是open狀態的話,adapter就不去open。
反之,adapter自己會開啟對應的connection的連線,在填充完畢後在自行close。
這也就說明,如果我們是多次填充的話,最好用程式碼顯示的Open和close資料庫連線,這樣會減少和資料庫建立連線的次數,提高效率。
如:
Conn.open();
Da.fill(ds);
Da.fill(ds1);
Conn.close();
     (5)fill方法
Adapter在填充的時,預設是不復製表的結構的,如主鍵和外來鍵,所以這樣的情況下,如果我們連續呼叫兩次fill的話,每次資料都會填充到dataset的對應表中。
如:da.Fill(ds1); da.Fill(ds1);這樣ds1.Tables[0]表中就會有重複記錄。
(6)當adapter從資料庫get多個表的時候,它會自動分別填充到不同的表中
cmd.CommandText = "SELECT CustomerID, CompanyName, ContactName, Phone FROM Customers WHERE CustomerID = 'ALFKI';SELECT OrderID, CustomerID, EmployeeID, OrderDate FROM Orders WHERE CustomerID = 'ALFKI'";
DbDataAdapter da = factory.CreateDataAdapter();
da.SelectCommand = cmd;
da.MissingSchemaAction = MissingSchemaAction.AddWithKey;
 DataSet ds = new DataSet();
da.Fill(ds);
(7)MissingSchemaAction屬性設定填充時是否獲取表結構的資訊,如主鍵和外來鍵等資訊
sqlConnection myConn = new SqlConnection(ConfigurationManager.ConnectionStrings["Northwind"].ToString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = myConn;
            cmd.CommandType = CommandType.Text;
            cmd.CommandText = "SELECT top 1 * FROM Region";
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            //da.MissingSchemaAction = MissingSchemaAction.AddWithKey;如果按照預設的情況,3次填充會填充3條一樣的記錄,如果設定,則只有1條資料。
            DataSet ds = new DataSet();
            myConn.Open();
            ds.EnforceConstraints = false;
            da.Fill(ds);
            da.Fill(ds);
            da.Fill(ds);
        myConn.Close();
(8)FillSchema Method
         (9)提高填充效率 設定的是Dataset的屬性
                            ds.EnforceConstraints = false;
            da.Fill(ds);
            ds.EnforceConstraints = true;//這裡設定這個屬性沒有什麼實際意義,因為只有一個表,如果是多表,並且表與表之間有1對1或1對多的關係的話,則可以提高效率
三、 Data Adapter的update方法
主要是要設定對應的command命令,設定這樣的命名通常有4種方法:
(1)         手動設定使用text或儲存過程      //提倡使用
(2)         使用DataCommandBuilder   //做Demo的時候經常使用
(3)         使用嚮導
(4)         System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
然後再使用 this.sqlInsertCommand1.CommandText = resources.GetString("sqlInsertCommand1.CommandText");來獲得CommandText。
當然,還要新增parameters.
需要注意的是,通常為了提高效率,我們把這些功能分配給幾個adapter物件單獨完成讀和更新或插入的功能。
在更新時,我們要在命令或儲存過程中解決衝突。
四、 Data Adapter的併發程式設計
處理併發的原則有兩個Optimistic Concurrency Options和pessimistic concurrency。pessimistic concurrency通常不使用,因為會帶來種種不好的因素,而且我們通常可以使用事務來達到相同的效果。Optimistic Concurrency Options也有很多策略。
處理併發主要依據的是每個單元格的幾個狀態值,如original,current等等,通過與資料庫對應值比較,我們就可以知道是否有併發,然後在根據我們實際需要的策略去解決併發問題。
附1:手動設定command命令Demo
ManuallyConfiguringDataAdapterCommandsDemo();
private void ManuallyConfiguringDataAdapterCommandsDemo()
        {
            SqlConnection myConn = new SqlConnection(ConfigurationManager.ConnectionStrings["Northwind"].ToString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = myConn;
            cmd.CommandType = CommandType.Text;
            cmd.CommandText = "SELECT * FROM Region";
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            da.MissingSchemaAction = MissingSchemaAction.AddWithKey;
            DataSet ds = new DataSet();
            ds.EnforceConstraints = false;
            da.Fill(ds);
            ds.EnforceConstraints = true;
            dataGridView1.DataSource = ds.Tables[0];
            //do sth like updating deleting and inserting
            DataRow newRow = ds.Tables[0].NewRow();
            newRow.BeginEdit();
            newRow["RegionID"] = 6;
            newRow["RegionDescription"] = "Russian";
            newRow.EndEdit();
            ds.Tables[0].Rows.Add(newRow);
            DataRow delRow = ds.Tables[0].Rows.Find(2);
            delRow.Delete();
            DataRow updateRow = ds.Tables[0].Rows.Find(1);
            updateRow["RegionDescription"] = "Updated";
            //update the changes into the database manually
            SqlCommand cmdUpdate = CreateUpdateCommand(myConn);
            SqlCommand cmdInsert = CreateInsertCommand(myConn);
            SqlCommand cmdDelete = CreateDeleteCommand(myConn);
            DataViewRowState dvrs = DataViewRowState.ModifiedCurrent | DataViewRowState.Deleted | DataViewRowState.Added;
            int intRowsAffected = 0;
            myConn.Open();
            foreach (DataRow row in ds.Tables[0].Select("", "", dvrs))
            {
                switch (row.RowState)
                {
                    case DataRowState.Modified:
                        intRowsAffected = SubmitUpdate(row, cmdUpdate);
                        break;
                    case DataRowState.Added:
                        intRowsAffected = SubmitInsert(row, cmdInsert);
                        break;
                    case DataRowState.Deleted:
                        intRowsAffected = SubmitDelete(row, cmdDelete);
                        break;
                }
                if (intRowsAffected == 1)
                    row.AcceptChanges();
                else
                    row.RowError = "Update attempt failed";
            }
            myConn.Close();
        }
    
        private int SubmitUpdate(DataRow row, SqlCommand cmd)
        {
            SqlParameterCollection pc = cmd.Parameters;
            pc["@RegionID"].Value = row["RegionID"];
            pc["@RegionDescription"].Value = row["RegionDescription"];
            return cmd.ExecuteNonQuery();
        }
        private int SubmitInsert(DataRow row, SqlCommand cmd)
        {
            SqlParameterCollection pc = cmd.Parameters;
            pc["@RegionID"].Value = row["RegionID"];
            pc["@RegionDescription"].Value = row["RegionID"];
            return cmd.ExecuteNonQuery();
        }
        private int SubmitDelete(DataRow row, SqlCommand cmd)
        {
            SqlParameterCollection pc = cmd.Parameters;
            pc["@RegionID"].Value = row["RegionID", DataRowVersion.Original];
            try
            {
                return cmd.ExecuteNonQuery();
            }
            catch
            {
                return 0;
            }
        }
        public SqlCommand CreateUpdateCommand(SqlConnection conn)
        {
            string strSQL;
            strSQL = "update [Region] set RegionDescription=@RegionDescription" + " where RegionID=@RegionID";
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = strSQL;
            cmd.CommandType = CommandType.Text;
            SqlParameterCollection pc = cmd.Parameters;
            pc.Add("@RegionDescription", SqlDbType.NChar, 50, "RegionDescription");
            pc.Add("@RegionID", SqlDbType.Int, 0, "RegionID");
            return cmd;
        }
        public SqlCommand CreateInsertCommand(SqlConnection conn)
        {
            string strSQL;
            strSQL = "insert into [Region] values(@RegionID,@RegionDescription)";
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = strSQL;
            cmd.CommandType = CommandType.Text;
            SqlParameterCollection pc = cmd.Parameters;
            pc.Add("@RegionDescription", SqlDbType.NChar, 50, "RegionDescription");
            pc.Add("@RegionID", SqlDbType.Int, 0, "RegionID");
            return cmd;
        }
        public SqlCommand CreateDeleteCommand(SqlConnection conn)
        {
            string strSQL;
            strSQL = "delete from [Region] where RegionID=@RegionID";
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = strSQL;
            cmd.CommandType = CommandType.Text;
            SqlParameterCollection pc = cmd.Parameters;
            pc.Add("@RegionID", SqlDbType.Int, 0, "RegionID");
            return cmd;
        }
附2:使用Commandbuilder
///The CommandBuilder can generate updating logic if all of the following are true:
            //Your query returns data from only one table.
            //That table has a primary key.
            //The primary key is included in the results of your query.
            SqlConnection myconn = new SqlConnection(ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString);
            //string strSQL = @"SELECT OrderID, ProductID, Quantity, UnitPrice FROM [OrderDetails] WHERE rderID = '10248' ORDER BY ProductID";
            string strSQL = "SELECT * FROM Region";
            SqlCommand cmd = new SqlCommand();
            cmd.CommandText = strSQL;
            cmd.CommandType = CommandType.Text;
            cmd.Connection = myconn;
            SqlDataAdapter da = new SqlDataAdapter(strSQL, myconn);
            SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(da);
            da.InsertCommand = cmdBuilder.GetInsertCommand();
            da.UpdateCommand = cmdBuilder.GetUpdateCommand();
            da.MissingSchemaAction = MissingSchemaAction.AddWithKey;
            //da.DeleteCommand = cmdBuilder.GetDeleteCommand();
            //do sth like updating deleting and inserting
            DataSet ds = new DataSet();
            ds.EnforceConstraints = false;
            da.Fill(ds);
            ds.EnforceConstraints = true;//這裡設定這個屬性沒有什麼實際意義,因為只有一個表,如果是多表填充的話,則可以提高效率
            //DataRow newRow = ds.Tables[0].NewRow();
            //newRow.BeginEdit();
            //newRow["RegionID"] = 6;
            //newRow["RegionDescription"] = "Russian";
            //newRow.EndEdit();
            //ds.Tables[0].Rows.Add(newRow);
            //DataRow delRow = ds.Tables[0].Rows.Find(2);
            //delRow.Delete();
            DataRow updateRow = ds.Tables[0].Rows.Find(1);
            updateRow["RegionDescription"] = "Eastern";
            da.Update(ds);
 

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/25897606/viewspace-704292/,如需轉載,請註明出處,否則將追究法律責任。

相關文章