locked
reader.ReadAsync() throwing exception "System.NotSupportedException" RRS feed

  • Question

  • Hi,

    I am trying to read XML data from stored procedures asynchronously as shown below:

    var command = new SqlCommand(connection);
           
    using (var reader = await cmd.ExecuteXmlReaderAsync())
    {
        while (await reader.ReadAsync())    <---------  This line throws exception
        {
            //read data and process 
        }
                                    
    }

    Below is the stacktrace

    "Specified method is not supported."
    
    StackTrace:
    
    at System.Xml.XmlSqlBinaryReader.ReadAsync()
       at CodeFirstStoredProcs.CodeFirstStoredProcs.<ReadXMLFromStoredProcAsync>d__25.MoveNext()  in DDProcsLayer.cs:line 892

    I tried to set the async property true

    reader.Settings.Async = true;

    But it doesn't work, since that property is readonly. 

    Any help is appreciated.


    San

    Tuesday, August 27, 2013 5:32 PM

Answers

  • Hello,

    Welcome toMSDN Support Forum.

    From your description, you want to know how to read XML data asynchronously.

    If I have misunderstood, please let me know.

    With your codes, I made a sample and please see the code below:

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.SqlClient;
    using System.Data.SqlTypes;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Threading.Tasks;
    using System.Xml;
    namespace ADONET
    {
        class S2013_08_28_1
        {
            internal void Show()
            {
                //1.Create A Connection             
                string connectionString = "server=(localdb)\\v11.0;database=TestDataBase;Integrated Security=True;";
                XmlTextWriter tw;
                SqlConnection connection = new SqlConnection(connectionString);
                connection.Open();
                SqlCommand command = new SqlCommand("select * from course FOR XML AUTO, XMLDATA", connection);
                var settingsField = typeof(SqlXml).GetField("DefaultXmlReaderSettingsCloseInput", BindingFlags.Static | BindingFlags.NonPublic);
                var settings = (XmlReaderSettings)settingsField.GetValue(null);
                settings.Async = true;
                using (var reader = command.ExecuteXmlReaderAsync())
                {
                    //reader.Result.Settings.Async = true;
                    while (reader.Result.ReadAsync().Result)    //<---------  This line throws exception
                    {
                        //read data and process 
                    }
                }
                connection.Close();
                //return ds; 
                Console.ReadLine();
            }
        }
    }

    As you mentioned, it will fail to set reader.Settings.Async = true directly.

    Because the object is created by command.ExecuteXmlReaderAsync(), its Settings.Async is false default and cannot be modify.

     So we have to set async to be true like below:

                var settingsField = typeof(SqlXml).GetField("DefaultXmlReaderSettingsCloseInput", BindingFlags.Static | BindingFlags.NonPublic);
                var settings = (XmlReaderSettings)settingsField.GetValue(null);
                settings.Async = true

    I look forward to hearing from you.

    Best Regards.


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    • Marked as answer by Fred Bao Tuesday, September 3, 2013 1:05 AM
    Wednesday, August 28, 2013 7:35 AM

All replies

  • Hello,

    Welcome toMSDN Support Forum.

    From your description, you want to know how to read XML data asynchronously.

    If I have misunderstood, please let me know.

    With your codes, I made a sample and please see the code below:

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.SqlClient;
    using System.Data.SqlTypes;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Threading.Tasks;
    using System.Xml;
    namespace ADONET
    {
        class S2013_08_28_1
        {
            internal void Show()
            {
                //1.Create A Connection             
                string connectionString = "server=(localdb)\\v11.0;database=TestDataBase;Integrated Security=True;";
                XmlTextWriter tw;
                SqlConnection connection = new SqlConnection(connectionString);
                connection.Open();
                SqlCommand command = new SqlCommand("select * from course FOR XML AUTO, XMLDATA", connection);
                var settingsField = typeof(SqlXml).GetField("DefaultXmlReaderSettingsCloseInput", BindingFlags.Static | BindingFlags.NonPublic);
                var settings = (XmlReaderSettings)settingsField.GetValue(null);
                settings.Async = true;
                using (var reader = command.ExecuteXmlReaderAsync())
                {
                    //reader.Result.Settings.Async = true;
                    while (reader.Result.ReadAsync().Result)    //<---------  This line throws exception
                    {
                        //read data and process 
                    }
                }
                connection.Close();
                //return ds; 
                Console.ReadLine();
            }
        }
    }

    As you mentioned, it will fail to set reader.Settings.Async = true directly.

    Because the object is created by command.ExecuteXmlReaderAsync(), its Settings.Async is false default and cannot be modify.

     So we have to set async to be true like below:

                var settingsField = typeof(SqlXml).GetField("DefaultXmlReaderSettingsCloseInput", BindingFlags.Static | BindingFlags.NonPublic);
                var settings = (XmlReaderSettings)settingsField.GetValue(null);
                settings.Async = true

    I look forward to hearing from you.

    Best Regards.


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    • Marked as answer by Fred Bao Tuesday, September 3, 2013 1:05 AM
    Wednesday, August 28, 2013 7:35 AM
  • Hi Fred,

    Thanks for the response.

    But I wonder how is command object's xmlreader setting are changed by below code:

    var settingsField = typeof(SqlXml).GetField("DefaultXmlReaderSettingsCloseInput", BindingFlags.Static | BindingFlags.NonPublic);
    
    var settings = (XmlReaderSettings)settingsField.GetValue(null);
    
    settings.Async = true

    We are not referring xmlreader used by command object in above code. 

    Is anything missing here ?


    San

    Wednesday, August 28, 2013 7:45 PM
  • Hello,

    >>But I wonder how is command object's xmlreader setting are changed by below code.

    There is a link that show how xmlreadersettings works for xmlreader object.

    http://msdn.microsoft.com/en-us/library/system.xml.xmlreadersettings.aspx

    >> We are not referring xmlreader used by command object in above code.

    You can see that the return value of command.ExecuteXmlReaderAsync() is Task<XmlReader>.

    And I should explain that why we need to set the async = true using xmlreadersetting.

    There is some introduce for xmlreader object on msdn:

    You must set this value to true when you create a new XmlReader instance if you want to use asynchronous XmlReader methods on that instance. After the XmlReader instance is created, the Async property is read-only. The default value of this property is false.

    This flag is ignored by the XmlReader.Create overload. This means that if you create a new XmlReader based on an existing XmlReader, the async behavior depends on the input XmlReader, and you cannot use the Async flag to change the async behavior.

    This is the link:

    http://msdn.microsoft.com/en-us/library/system.xml.xmlreadersettings.async.aspx

    So for that we have to use xmlreadersetting object to set xmlreader object.

    I look forward to hearing from you.

    Best Regards.


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    Thursday, August 29, 2013 2:25 AM