views:

416

answers:

0

I have a legacy VB 6 client app, which uses a VB ActiveX control, which then communicates via DCOM to a VB component registered in the COM+ Catalog. The VB COM+ component communicates with a .NET component, also registered in the COM+ Catalog.

I have an issue when our COM+ application Activation is set to Server, which is required to make an application proxy. When a recordset is being returned to the VB component (if it's registered with COM+), from the .NET component also registered with COM+, an error is thrown:

Multiple-step operation generated errors. Check each status value.

Error Number: -2147217887 Source: Microsoft Cursor Engine

If the COM+ application is set to Library, this issue doesn't occur.

If the VB component is registered (regsvr32) but not added to the COM+ Catalog, this issue doesn't occur.

The error happens right when the Recordset is being returned from .NET to the VB component, immediately after the .NET method returns, but before it gets back to the VB component, so it's happening in COM+.

This is the method in the .NET component that trys to return, but can't unless everything has an activation type of library:

        [Guid("192BC4DF-3683-44de-B873-50E1E1B6912F")]
    public interface IRecordSetUtil
    {
        System.Data.DataSet ConvertToDataSet(ADODB.Recordset rs);
        ADODB.Recordset ConvertToRecordset(DataSet ds, string dbName);
    }

    [Transaction(TransactionOption.Required, Isolation = TransactionIsolationLevel.Serializable)]
    [ObjectPooling(true)]
    [Guid("D61997C5-E910-4a59-9B37-F6D2989578A8")]
    [ClassInterface(ClassInterfaceType.None)]
    public class CRecordSetUtil : CDatabase, IRecordSetUtil
    {
        [AutoComplete]
        public DataSet ConvertToDataSet(ADODB.Recordset rs)
        {
            DataSet ds = new DataSet();
            ADODB.Stream oStream = new ADODB.StreamClass();
            ADODB.Recordset oRsClone = new ADODB.Recordset();
            try
            {
                //save the recordset to the stream object            
                rs.Save(oStream, ADODB.PersistFormatEnum.adPersistADTG);

                //and now open the stream object into a new recordset
                oRsClone.Open(oStream, Missing.Value, ADODB.CursorTypeEnum.adOpenUnspecified, ADODB.LockTypeEnum.adLockUnspecified, 0);

                System.Data.OleDb.OleDbDataAdapter oAdapter = new System.Data.OleDb.OleDbDataAdapter();

                // oRsClone is closed automatically after fill
                oAdapter.Fill(ds, oRsClone, "ConvertedRecordset");

            }
            finally
            {
                oStream.Close();
            }
            return ds;
        }

        [AutoComplete]
        public ADODB.Recordset ConvertToRecordset(DataSet ds, string dbName)
        {
            //Create a MemoryStream to contain the XML
            MemoryStream mStream = new MemoryStream();
            XmlTextWriter xWriter = new XmlTextWriter(mStream, null);

            //Additional formatting for XML
            xWriter.Indentation = 8;
            xWriter.Formatting = Formatting.Indented;
            //call this Sub to write the ADONamespaces
            WriteADONamespaces(xWriter);
            //call this Sub to write the ADO Recordset Schema
            WriteSchemaElement(ds, dbName, xWriter);
            //Call this sub to transform the data portion of the Dataset
            TransformData(ds, xWriter);
            //Flush all input to XmlWriter
            xWriter.Flush();

            //Prepare the XML to pass to an ADODB.Stream and then a Recordset
            mStream.Position = 0;
            byte[] buffer = new byte[mStream.Length];
            mStream.Read(buffer, 0, buffer.Length);

            var textConverter = new UTF8Encoding();
            string sXml = textConverter.GetString(buffer);

            ADODB.Stream oStream = new ADODB.StreamClass();
            oStream.Open(Missing.Value, ADODB.ConnectModeEnum.adModeUnknown, ADODB.StreamOpenOptionsEnum.adOpenStreamUnspecified, "", "");

            //Give the XML string to the ADO Stream
            oStream.WriteText(sXml, ADODB.StreamWriteEnum.adWriteChar); 
            oStream.Position = 0;

            //Open a recordset from the stream
            ADODB.Recordset oRecordset = new ADODB.Recordset();

            oRecordset.Open(oStream, Missing.Value, ADODB.CursorTypeEnum.adOpenUnspecified, ADODB.LockTypeEnum.adLockUnspecified, 0);

            oStream.Close();

            return oRecordset;
        }
}

I tried a simple test, with a VB 6 exe, a single VB class registered in the COM+ catalog, invoking a simple .NET Enterprise Services component. I only get the error if I try to return an ADODB.Recordset. If I return a string (like one of the field values), it works fine.

Ideas?

Update: If I just try to return the XML as a string, I get the same issue.