Microsoft Knowledge Base Article
This article contents is Microsoft Copyrighted material.
©2005-©2007 Microsoft Corporation. All rights reserved.
Terms
of Use |
Trademarks
Article ID: 313510 - Last Review: March 10, 2006 - Revision: 2.2
BUG: Error message when you call an OleDbDataReader object: System.InvalidCastException: QueryInterface for interface IRowset failed
This article was previously published under Q313510
On This Page
SYMPTOMS
When you call an
OleDbDataReader object that invokes the
Read method from a different single-threaded apartment (STA) thread
than the object was created in, you receive the following exception:
System.InvalidOperationException: The
OleDbDataReader.Read must be used from the same thread on which is was created
if that thread's ApartmentState was not ApartmentState.MTA
CAUSE
This behavior occurs because the component that implements
IRowset does not aggregate the free-threaded marshaller, even though it is
marked with a threading model of both. This causes OLE32 to use its own
IMarshal, which requires either a typelib or a proxy and stub to be registered
for the interface.
RESOLUTION
To work around this issue, make sure that you use an
OleDB object only from the STA thread that it is created in, or from
any multithreaded apartment (MTA) if it was created on an MTA.
STATUS
Microsoft has confirmed that this is a bug in the Microsoft
products that are listed at the beginning of this article.
MORE INFORMATION
Steps to Reproduce the Problem
- Use Notepad or another text editor to create a C# file
named STA_bug.cs with the following code:
using System;
using System.Data;
using System.Data.OleDb;
using System.Diagnostics;
using System.Threading;
public class Class1 {
static public ManualResetEvent s_resetevent;
static public OleDbDataReader s_datareader;
static public void Main(string[] args) {
Thread.CurrentThread.ApartmentState = ApartmentState.STA; // MTA works
try {
BugMultiThread();
}
catch(Exception e) {
Console.WriteLine(e.ToString());
}
}
static public void BugMultiThread() {
// We use NT authentication here.
OleDbConnection connection = new OleDbConnection("Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=pubs;Data Source=(local)");
// If you want to use SQL Mode authentication,
// make necessary changes to point to your SQL Server.
// OleDbConnection connection = new OleDbConnection("Provider=SQLOLEDB;Data Source=myserver;Initial Catalog=pubs;User ID=username;Password=password;");
connection.Open();
try {
OleDbCommand command = new OleDbCommand("select top 2 * from authors; select top 2 * from publishers;", connection);
s_datareader = command.ExecuteReader();
s_resetevent = new ManualResetEvent(false);
(new Thread(new ThreadStart(BugMultiThreadRead))).Start();
s_resetevent.WaitOne();
}
finally {
if ((null != s_datareader) && !s_datareader.IsClosed) {
s_datareader.Close();
}
connection.Close();
}
}
static public void BugMultiThreadRead() {
try {
Console.WriteLine("BugMultiThreadRead: start");
if (null != s_datareader) {
try {
do {
while (s_datareader.Read()) {
Console.Write(".");
}
Console.Write("*");
} while (s_datareader.NextResult());
}
catch(Exception e) {
Console.WriteLine();
Console.WriteLine(e.ToString());
}
Console.WriteLine();
}
}
finally {
Console.WriteLine("BugMultiThreadRead: signal finish");
s_resetevent.Set();
}
}
}
- Use the Visual Studio .NET command prompt to execute the
following command:
csc.exe /r:system.dll /r:system.data.dll STA_bug.cs & STA_bug.exe
Note that you receive the following exceptions:
BugMultiThreadRead: start
System.InvalidOperationException: The OleDbDataReader.Read must be used from the same thread on which is was created if that thread's
ApartmentState was not ApartmentState.MTA ---> System.InvalidCastException:
QueryInterface for interface IRowset failed.
at System.Data.Common.IRowset.GetNextRows(IntPtr hChapter, Int32 lRowsOffset, Int32 cRows, Int32& pcRowsObtained, IntPtr& pprghRows)
at System.Data.OleDb.OleDbDataReader.GetRowHandles()
--- End of inner exception stack trace ---
at System.Data.OleDb.OleDbDataReader.GetRowHandles()
at System.Data.OleDb.OleDbDataReader.ReadRowset()
at System.Data.OleDb.OleDbDataReader.Read()
at Class1.BugMultiThreadRead()
BugMultiThreadRead: signal finish
- If you make a revision to use MTA, as follows
Thread.CurrentThread.ApartmentState = ApartmentState.MTA;
you receive the correct result:
BugMultiThreadRead: start
..*..*
BugMultiThreadRead: signal finish
APPLIES TO
- Microsoft ADO.NET (included with the .NET Framework)
- Microsoft Visual Studio .NET 2002 Professional Edition, when used with:
- Microsoft Visual C# .NET 2002 Standard Edition
| kberrmsg kbbug kbvs2002sp1sweep KB313510 |
Community Feedback System
Very often, it takes hours to solve a problem. Very often, you've looked high
and low, and have tried a lot of solutions. When you finally found it, chances
are, it was because someone else helped you. Here's your chance to give back.
Use our community feedback tool to let others know what worked for you and what
didn't.
Please also understand that the community feedback system is not warranted to be
correct, it's simply a system that we've built to let people try and help each
other. If something in a feedback response doesn't make sense to you, or you're
not comfortable making changes that the feedback talks about (like registry
edits), please consult a professional.
Thank you for using kbAlertz.com Feedback System.
-- Scott Cate
Be the first to leave feedback, to help others about this knowledge base
article.
(Optional) Name
(Optional)
Public URL Or Email
Comments
No
HTML -- Text Only Please