Как заполнить параметр с табличным значением с помощью пользовательского DbDataReader?

Согласно MSDN, System.Data.SqlClient поддерживает заполнение табличных параметров из объектов DataTable, DbDataReader или IEnumerable<SqlDataRecord>.

Я написал следующий код, который заполняет пареметр с табличным значением, используя объекты IEnumerable<SqlDataRecord>:

static void Main()
{       
    List<int> idsToSend = ...
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();    
        SqlCommand command = new SqlCommand(@"SELECT ...
                                              FROM ... 
                                              INNER JOIN @ids mytable ON ...", connection);

        command.Parameters.Add(new SqlParameter("@ids", SqlDbType.Structured)
        {
            TypeName = "int_list_type",
            Direction = ParameterDirection.Input,
            Value = GetSqlDataRecords(idsToSend) //returns IEnumerable<SqlDataRecord> 
        });

        SqlDataReader reader = command.ExecuteReader();
        //consume reader...
    }
}

Это работает отлично.

На странице MSDN говорится:

Вы также можете использовать любой объект, производный от DbDataReader, для потоковой передачи строк данных в параметр, возвращающий табличное значение.

Вместо этого я хотел бы использовать пользовательский DbDataReader для передачи данных строки. Что-то вроде этого:

public class CustomDataReader : DbDataReader
{
    public CustomDataReader(IEnumerable<int> values)
    {           
    }

    //implementation of other abstract methods and fields required by DbDataReader
    //...
}

Я изменил следующую строку в исходном примере кода:

Value = GetSqlDataRecords(idsToSend)
=>
Value = new CustomDataReader(idsToSend)

Если я запускаю код, он дает мне следующее исключение во время выполнения command.ExecuteReader() :

Произошло необработанное исключение типа «System.NotSupportedException» в System.Data.dll. Дополнительная информация: указанный метод не поддерживается.

Я поставил точку останова на ВСЕ методы и свойства моего класса CustomDbDataReader: ни один из них не вызывается до того, как я получил исключение, поэтому, вероятно, это не связано с реализацией DbDataReader


РЕДАКТИРОВАТЬ: вот трассировка стека по запросу:

   at System.Data.SqlClient.TdsParser.TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, Int32 timeout, Boolean inSchema, SqlNotificationRequest notificationRequest, TdsParserStateObject stateObj, Boolean isCommandProc, Boolean sync, TaskCompletionSource`1 completion, Int32 startRpc, Int32 startParam)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds, Boolean describeParameterEncryptionRequest)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader()
   at ConsoleApplication211.Program.Main() in Program.cs:line 51
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

person tigrou    schedule 20.03.2017    source источник
comment
Можете ли вы отредактировать вопрос, чтобы показать трассировку стека исключения   -  person stuartd    schedule 20.03.2017
comment
@stuartd: готово   -  person tigrou    schedule 20.03.2017
comment
stackoverflow.com/a/42099675/2996339   -  person meziantou    schedule 20.03.2017
comment
Единственная разница, которую я вижу, заключается в том, что она использует хранимую процедуру, является ли это требованием для использования DbDataReader?   -  person tigrou    schedule 20.03.2017


Ответы (1)


Вам необходимо реализовать GetSchemaTable, который не помечен как абстрактный.

См. также: Как получить схему столбцов с помощью метода DataReader GetSchemaTable и Visual C# .NET

person Lucero    schedule 20.03.2017