文章編號: 910696 - 上次校閱: 2007年11月28日 - 版次: 2.1

對於 [ADODB 主要 Interop 組件 (PIA) 隨附於 Visual Studio 2005 的已知的問題

系統提示本文適用於您使用的作業系統之外的作業系統。與您不相關的文章內容已停用。
警告 在 ADO 和 ADO MD 有不被完全環境中測試 Microsoft.NET Framework。它們可能會導致間歇性問題,特別是在服務為基礎的應用程式或在多執行緒應用程式中。本文中討論的技術應該只用於為暫時的量值 ADO.NET 的移轉過程。之後您有進行完整的測試,以確定是沒有相容性問題,您應該只使用這些技巧。利用這種方式中的 ADO 或 ADO MD 造成的問題是不受支援。如需詳細資訊請參閱下列的 「 Microsoft 知識庫 」 中的文件:
840667 ? (http://support.microsoft.com/kb/840667/ ) 在.NET Framework 應用程式中使用 ADO 和 ADO MD 時,您會收到未預期的錯誤

在此頁中

全部展開 | 全部摺疊

簡介

本文將告訴已知的問題如 [ADODB 主要 Interop 組件 (PIA) 隨附於 Microsoft Visual Studio 2005。

其他相關資訊

在記憶體回收 Microsoft Visual Basic 6.0 和 Microsoft Visual Basic.NET 之間的差異

在 Visual Basic 6.0 和 Visual Basic.NET 記憶體回收之間有主要的差異。主要的差異在於 Visual Basic 6.0 中的記憶體回收是更積極比 Visual Basic.NET 記憶體回收。與 Visual Basic 6.0 一旦物件執行個體超出範圍,會立即釋放物件。與 Visual Basic.NET 或一般.NET 記憶體回收,就不會發生相同的行為。與.NET 記憶體回收集合物件是以非同步的方式發行。

記憶體回收的差異呈淚您的資料存取程式碼上大型的效果,當您從 Visual Basic 6.0 中移至 Visual Basic.NET 時。

比方說,當物件回收由記憶體回收就關閉開啟 ADODB 資料錄集 物件。開發人員有經驗撰寫 Visual Basic 6.0 中的程式碼可能會依賴它們遷移到 Visual Basic.NET 的程式碼時,會改變的記憶體回收集合語意。因為.NET 記憶體回收是非同步和不具決定性,您可能無法看到所做的變更,即使基本測試就會發生。

如 Microsoft SQL Server 2000 資料庫的某些資料庫只支援單一使用中結果集,每個連線。如果您有 Firehose 指標開啟在連線到 SQL Server 連線會被封鎖,直到資料指標關閉為止。依預設值,OLE DB 提供者將會開啟額外的連線執行查詢,如果目前的連線無法執行該查詢。因此,許多 ActiveX 資料物件 (ADO) 使用者都不知道這項限制。這些額外的連線不會參與連接共用。開啟額外的連線時封鎖的連線參與交易的嘗試會失敗。

我們建議您檢閱您的 Visual Basic 6.0 中程式碼,並明確的關閉所有的 資料錄集 物件和連線。您的程式碼遷移至 Visual Basic.NET 後,然後,重新測試程式碼。

本節列出這個問題的三個範例和每個範例的程式碼範例。

範例 1: 其他連線開啟時您並不會明確地關閉資料錄集物件

在 Visual Basic 6.0 中執行下列程式碼範例時, 就需要只有一個單一的連線。因為當 資料錄集 物件超出範圍時隱含地關閉所 ExecuteQuery 程序中建立的 資料錄集 物件也是如此。 程式碼範例會使用 SQL Server @ @ SPID 變數來代表伺服器處理序識別項,用來執行查詢。 如果您在執行程式碼您會注意到查詢傳回相同的值在 @ @ spid 資料行。這個結果表示查詢被執行相同的連線上資料庫
Public Sub Main()
    Dim strConn As String
    Dim cn As ADODB.Connection
    
    strConn = "Provider=SQLOLEDB;Data Source=.;" & _
              "Initial Catalog=Northwind;Trusted_Connection=Yes;"
    
    Set cn = New ADODB.Connection
    cn.Open strConn
    
    cn.Properties("Multiple Connections").Value = False
    
    ExecuteQuery cn, "SELECT @@spid, * FROM Customers"
    ExecuteQuery cn, "SELECT @@spid, * FROM Customers"
End Sub

Private Sub ExecuteQuery(cn As ADODB.Connection, strSQL As String)
    Dim rs As ADODB.Recordset
    Set rs = cn.Execute(strSQL)
    MsgBox rs(0)
End Sub
如果您在中 Visual Basic.NET 使用類似的程式碼您會注意到第二個 資料錄集 物件包含 @ @ spid 的不同值 資料行。這個值表示查詢已執行不同的連線至資料庫。

這項行為是不同的因為 ExecuteQuery 程序中所建立的 資料錄集 物件未關閉,而且會保持開啟,直到.NET 記憶體回收行程清除 資料錄集 物件。 在 Microsoft.NET Framework 的記憶體回收就會以非同步方式發生。如果不 ExecuteQuery 程序會再次呼叫的時間已關閉 資料錄集 物件,SQL Server OLE DB 提供者將會開啟新的連線,執行第二個查詢。

如果在 ExecuteQuery 程序中新增 rs.Close 命令的呼叫您要確定相同的連線上會執行查詢。 您可以也明確告訴 SQL Server OLE DB 提供者不來開啟其他連接。若要執行此動作加入在下列程式碼行的程式碼在開啟連線之後立刻:
cn.Properties("Multiple Connections").Value = False
這個程式碼會讓 SQL Server OLE DB 提供者擲回例外狀況,每次 OLE DB 提供者否則會開啟額外的連線。

範例 2: 問題時,會發生您使用交易如果您不執行明確關閉資料錄集物件

封鎖的連線參與交易時,無法開啟額外的連線。 在 Visual Basic 6.0 中執行下列程式碼範例時,程式碼會在單一連接已開啟的交易上執行多個查詢。 程式碼會呼叫下列兩個功能:
  • GetCustomers
  • GetOrders
每個函式會開啟 資料錄集 物件
Public Sub Main()
    Dim cn As ADODB.Connection
    Set cn = New ADODB.Connection
    cn.Open "Provider=SQLOLEDB;Data Source=.;" & _
            "Initial Catalog=Northwind;Trusted_Connection=Yes;"
    
    cn.BeginTrans
    
    GetCustomers cn
    GetOrders cn
    
    cn.RollbackTrans
    cn.Close
End Sub

Public Sub GetCustomers(Connection As ADODB.Connection)
    Dim rs As ADODB.Recordset
    Set rs = Connection.Execute("SELECT CustomerID, CompanyName FROM Customers")
End Sub

Public Sub GetOrders(Connection As ADODB.Connection)
    Dim rs As ADODB.Recordset
    Set rs = Connection.Execute("SELECT OrderID, CustomerID FROM Orders")
End Sub
所藉由呼叫 GetCustomers 函式建立的 資料錄集 物件隱含關閉在 Visual Basic 6.0 中該函式呼叫的結尾。這種行為將會說明"範例 1: 其他連線開啟時您並不會明確地關閉資料錄集物件 」 區段。不過,該 資料錄集 物件可能不會關閉依您的程式碼在 Visual Basic.NET 呼叫 GetOrders 函式的時間。因此,目前連線到 SQL Server 有開啟的結果集,客戶資訊。因為目前的連線忙碌所以擷取 GetOrders 函式中查詢結果需要新的隱含建立連線。但是,您無法建立隱含的連接,只要是開啟的交易。因此,程式碼將會失敗,並且您會收到下列錯誤訊息:
無法建立新的連線,因為處於手動或分散式異動模式。
若要解決這個問題,明確關閉使用 GetCustomers] 和 [GetOrders 函式所建立的 資料錄集 物件。

範例 3: 問題時,會發生您隱含建立,並放棄資料錄集物件

預設情況下,Execute 方法的 連線] 及 [指令] 物件會隱含建立,並傳回新的 資料錄集 物件。 在 Visual Basic 6.0 中如果此 資料錄集 物件不物件變數在維護 資料錄集 物件超出範圍,並將立即關閉。 因此,下列程式碼範例成功地在執行 Visual Basic 6.0 中。但是,您將會收到錯誤訊息中所提到"範例 2: 當您使用交易如果您不執行明確關閉資料錄集物件時,就會發生問題 」 區段如果程式碼移轉到 Visual Basic.NET
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
cn.Open "Provider=SQLOLEDB;Data Source=.;" & _
        "Initial Catalog=Northwind;Trusted_Connection=Yes;"

cn.BeginTrans

cn.Execute "SELECT CustomerID, CompanyName FROM Customers"
cn.Execute "SELECT OrderID, CustomerID FROM Orders ORDER BY CustomerID"

cn.RollbackTrans
cn.Close
在這個程式碼] 範例 Execute 方法的 連線 物件的呼叫隱含地傳回 資料錄集 物件。在 Visual Basic 6.0 中的記憶體回收立即關閉每個 資料錄集 物件,因為傳回的值不儲存在變數中。無法侵略性的在 Visual Basic.NET 記憶體回收。資料錄集 物件,其中包含客戶資訊仍為開啟狀態時呼叫查詢資料庫中的訂單資訊,就會發生。您收到錯誤訊息中所提到的因此,"範例 2: 當您使用交易如果您不執行明確關閉資料錄集物件時,就會發生問題 」 區段。

若要解決這個問題,傳遞從 ExecuteOptionsEnum選項 參數的 Execute 方法中的 [adExecuteNoRecords 值]。當您執行這項操作時可以指出 Execute 方法不應傳回一個 資料錄集 物件如所示
cn.Execute "SELECT CustomerID, CompanyName FROM Customers", , _
           ADODB.ExecuteOptionsEnum.adExecuteNoRecords
,下列程式碼範例。

問題 2: 我們不建議 ADODB PIA 壓力案例

我們強烈防止您從使用 ADODB PIA 壓力案例下例如,在多使用者的 Microsoft ASP.NET 或 Microsoft COM + 元件。 當 Microsoft 測試團隊進行測試 ADODB PIA 時,測試小組會找到 ADODB PIA 失敗壓力之下。 如果.NET 資料存取程式碼必須可靠地在強大壓力下執行,我們強烈建議您在使用 ADO.NET 來撰寫程式碼。

問題 3: 我們不建議您在 64 位元模式使用 ADODB PIA

我們強烈防止您無法在 64 位元應用程式中使用 ADODB PIA。 ADODB PIA 尚未經過測試在 64 位元模式。 大多數的 64 位元案例牽涉到如 ASP.NET 或 COM + 高壓力伺服器端元件。 ADODB PIA 有已知問題在壓力下執行。64 位元模式較少使用 ADODB PIA 的嶄新,也可以讓有限的可用性的 64 位元 OLE DB 提供者。

問題 4: 失敗當您使用就會發生晚期繫結查詢執行

ADODB 支援兩種形式的晚期繫結查詢執行。執行晚期繫結查詢可讓您在 COM 中使用 IDispatch 繫結執行查詢,查詢就像 連線 物件上的方法。ADODB 支援兩種晚期繫結查詢執行下列形式:
  • 若要建立 「 具名 」 查詢設定 Command 物件的 [名稱] 屬性。
  • 執行預存程序呼叫。
當您將程式碼從 Visual Basic 6.0 中移轉到 Visual Basic.NET 時,可能會遇到這些表單的問題。

下列範例說明這些問題。

範例 1: 如果您建立具有相同名稱的第二個晚期繫結查詢時,會查詢失敗

下列的程式碼範例會建立兩個 命令 物件的 [名稱] 屬性使用相同的值的晚期繫結查詢
Dim cn As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Dim strConn As String
    
'Open a new Connection.
strConn = "Provider=SQLOLEDB;Data Source=.;" & _
          "Initial Catalog=Northwind;Trusted_Connection=Yes"
Set cn = New ADODB.Connection
cn.Open strConn
    
'Create a Command object, and then set the Name property 
'to enable the Command object as a late-bound method call.
Set cmd = New ADODB.Command
cmd.CommandText = "SELECT COUNT(*) FROM Customers"
cmd.Name = "GetCount"
Set cmd.ActiveConnection = cn
    
'Execute the Command object as a late-bound method call on the Connection.
Set rs = New ADODB.Recordset
cn.GetCount rs
Debug.Print rs(0).Value
rs.Close
Set rs = Nothing
    
'Release the Command object.
Set cmd = Nothing
    
'Create a new Command object, and then set the Name property
'to enable the Command object as a late-bound method call.
Set cmd = New ADODB.Command
cmd.CommandText = "SELECT COUNT(*) FROM Orders"
cmd.Name = "GetCount"
Set cmd.ActiveConnection = cn
    
'Execute the Command object as a late-bound method call on the Connection object.
Set rs = New ADODB.Recordset
cn.GetCount rs
Debug.Print rs(0).Value
rs.Close
Set rs = Nothing
    
'Clean up.
cn.Close
Visual Basic 6.0 中只要 命令 物件設定為 Nothing,物件會回收由記憶體回收。 連線 物件會被通知 Command 物件已被摧毀。 因此,第二個 命令 物件與 連線 物件相關聯時,沒有衝突存在。

在 Visual Basic.NET 中執行類似的程式碼時,Command 物件可能不回收由記憶體回收,由第二個 命令 物件是與 連線 物件相關聯的時間。因此,可能會收到下列的例外狀況錯誤訊息:
物件已存在於集合中。無法附加。
如果要解決這個問題,您必須以手動方式解除關聯第一個 命令 物件從 連線 物件。若要執行此動作明確地呼叫 cmd.ActiveConnection 方法時清除 命令 物件。如果要執行這項操作,使用
'Visual Basic 6.0 syntax
Set cmd.ActiveConnection = Nothing

'Visual Basic .NET syntax
cmd.ActiveConnection = Nothing
下列程式碼範例。

範例 2: 如果您在第二個連線上呼叫晚期繫結查詢,會查詢失敗

下列程式碼範例會執行下列工作,它們依照的順序:
  1. 建立兩個 連線 物件。
  2. 在每個 連線 物件上建立 命令 物件。每個 命令 物件都有 名稱 屬性的值相同。
  3. 利用晚期繫結查詢執行執行每個命令。
Dim strConn As String, strSQL As String
Dim cn1 As ADODB.Connection, cn2 As ADODB.Connection
Dim cmd1 As ADODB.Command, cmd2 As ADODB.Command
Dim rs1 As ADODB.Recordset, rs2 As ADODB.Recordset
    
strConn = "Provider=SQLOLEDB;Data Source=.;" & _
          "Initial Catalog=Northwind;Trusted_Connection=Yes;"
strSQL = "SELECT COUNT(*) FROM Customers"
    
'Open connections.
Set cn1 = New ADODB.Connection
Set cn2 = New ADODB.Connection
cn1.Open strConn
cn2.Open strConn
    
'Create commands so that the commands can be executed as late-bound methods.
Set cmd1 = New ADODB.Command
Set cmd2 = New ADODB.Command
cmd1.CommandText = strSQL
cmd2.CommandText = strSQL
cmd1.Name = "GetCount"
cmd2.Name = "GetCount"
Set cmd1.ActiveConnection = cn1
Set cmd2.ActiveConnection = cn2
    
'Execute queries as late-bound methods.
Set rs1 = New ADODB.Recordset
Set rs2 = New ADODB.Recordset
cn1.GetCount rs1
cn2.GetCount rs2
MsgBox rs1(0).Value
MsgBox rs2(0).Value
    
'Clean up.
rs1.Close
rs2.Close
cn1.Close
cn2.Close
當您使用 Visual Basic 6.0 中,這個程式碼範例就會成功。不過,這個程式碼範例會失敗,當您使用 Visual Basic.NET。這項失敗發生的原因,是因為以下原因:
  • ADODB 準備這些查詢做為晚期繫結方法的方式
  • Visual Basic.NET 編譯器進行有關這些方法的假設
當您設定的 命令 物件 ActiveConnection 屬性時,ADODB 會檢查 命令 物件是否具有 [名稱] 屬性設定。如果 名稱 屬性設定,ADODB 會準備查詢,以便為晚期繫結方法,連線 物件上執行查詢。在此範例將兩個 命令 物件會有 CommandText 屬性的值相同。不過,這是非常簡化的範例。雖然 命令 物件有 名稱 屬性的值相同,命令 物件可能有 CommandText 值會執行非常不同的查詢。因此,ADODB 會產生唯一的方法簽名碼為晚期繫結方法。

Visual Basic.NET 編譯器並不會讓此區分。上 GetCount 」 查詢的第一次呼叫,Visual Basic.NET 編譯器會快取方法簽名碼,以防 GetCount 方法 連線 物件上進行另一個呼叫。當程式碼會呼叫第二個 GetCount 」 查詢時,Visual Basic.NET 就會重複使用快取的方法簽名碼的第二個 GetCount 方法。因為 ADODB 會產生唯一的方法簽名碼,到第二個晚期繫結查詢呼叫會失敗。

沒有因應措施存在於此案例中。

問題 5: 可以設定一些 ADODB Variant 資料型別到字串資料型別

ADODB 物件模型可讓您設定某些屬性為字串,或是其他 ADODB 物件。比方說 資料錄集 物件的 ActiveConnection 屬性會出現在 Visual Basic 6.0 物件瀏覽器為 Variant 資料型別,並且可以被設定成 連線 物件或連接字串。

如果您已經建立您自己的物件,且想要支援這項功能,您必須建立個別的屬性存取子。如果要執行這項操作,使用類似下列程式碼範例的程式碼的程式碼
Public Property Let ActiveConnection (ByVal value As String)
    'Add logic here.
End Property

Public Property Set ActiveConnection (ByRef value As Object)
    'Add logic here.
End Property
的.NET Framework 是有點更嚴格,而且不允許為使用不同資料型別的多個屬性存取子。ADODB PIA 可讓您將 資料錄集 物件的 ActiveConnection 屬性設定為 連線 物件。如果想將 ActiveConnection 屬性設定為一字串您就必須使用 let_ActiveConnection 方法,如下列程式碼範例所示
Dim strConn As String
Dim rs As ADODB.Recordset
    
strConn = "Provider=SQLOLEDB;Data Source=.;" & _
          "Initial Catalog=Northwind;Trusted_Connection=Yes;"
rs = New ADODB.Recordset
rs.let_ActiveConnection(strConn)
相同的方法時,需要您設定下列屬性:
  • 資料錄集 物件的 [資料來源] 屬性
  • 命令 物件的 ActiveConnection 屬性
這些屬性接受物件。若要設定這些屬性為字串,您必須使用對應的 let_ MethodName 方法。

當問題 6: 一個 InvalidCastException 時,就會發生例外狀況呼叫 Parameters.Append 方法

ADODB PIA 隨附於 Microsoft Visual Studio.NET 2003年與 Visual Studio 2005 具有當您呼叫 Parameters.Append 方法一起使用預設的建構函式所建立的一個 參數 物件時所發生的已知的問題。

下列程式碼範例會造成 InvalidCastException 例外狀況
Dim cmd As ADODB.Command
Dim p As ADODB.Parameter

cmd = New ADODB.Command
cmd.CommandText = "SELECT CustomerID FROM Orders WHERE OrderID = ?"

p = New ADODB.Parameter
p.Name = "@OrderID"
p.Type = ADODB.DataTypeEnum.adInteger
p.Value = 10248

cmd.Parameters.Append(p)

若要解決這個問題,參數 物件使用建立的 指令 的物件 CreateParameter 方法如下列程式碼範例所示
Dim cmd As ADODB.Command
Dim p As ADODB.Parameter

cmd = New ADODB.Command
cmd.CommandText = "SELECT CustomerID FROM Orders WHERE OrderID = ?"

p = cmd.CreateParameter()
p.Name = "@OrderID"
p.Type = ADODB.DataTypeEnum.adInteger
p.Value = 10248

cmd.Parameters.Append(p)

您遇到問題處理元件預期 ADO 2.8 介面的問題 7:

ADODB PIA 隨附於 Visual Studio 2005 是相同的元件,是隨附在 Visual Studio.NET 2003年,並且藉由使用 Microsoft.NET Framework 1.1 已建置。ADODB PIA 互動,ADO 2.7 介面而建立,且尚未更新若要使用 ADO 2.8 介面。

因此,使用 ADODB PIA 搭配 ADO 2.8 介面會公開 (Expose) 的元件的嘗試失敗。 這種情況下不支援具有 ADODB PIA。

這篇文章中的資訊適用於:
  • Microsoft Visual Studio 2005 Professional Edition
  • Microsoft Visual Studio 2005 Standard Edition
  • Microsoft Visual Studio 2005 Team System Architect Edition
  • Microsoft Visual Studio 2005 Team System Developer Edition
  • Microsoft Visual Studio 2005 Team System Team Foundation:
  • Microsoft Visual Studio 2005 Team System Test Edition
  • Microsoft Visual Studio 2005 Express Edition
關鍵字:?
kbmt kbinfo KB910696 KbMtzh
機器翻譯機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:910696? (http://support.microsoft.com/kb/910696/en-us/ )
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。