SqlDataAdapter.FillSchema с хранимой процедурой с временной таблицей

У меня возникла проблема, аналогичная этому вопросу здесь (Отображение типа данных и размера столбца из результатов запроса SQL Server во время выполнения), для которого не было надежного решения.

Интересно, нашел ли кто-нибудь решение или обходной путь для этого. Я могу использовать SqlDataAdapter.Fill() без проблем, но .FillSchema() сообщит об ошибке, что временная таблица, которую я создаю в хранимой процедуре, не существует.

Моя цель - иметь возможность заполнить DataTable данными и схемой из источника.


person T L    schedule 24.09.2013    source источник


Ответы (3)


Я столкнулся с той же проблемой с SqlDataAdapter. Я смог решить проблему, изменив свой код, чтобы вместо этого использовать SqlDataReader.

Если вам вообще не нужно изменять схему

Следующие сегменты кода будут работать нормально, если вам не нужно манипулировать схемой вашего объекта DataTable и вы также планируете использовать данные, возвращаемые хранимой процедурой.

var command = new SqlCommand("stored procedure name")
{
    CommandType = CommandType.StoredProcedure 
};

var adapter = new SqlDataAdapter(command);
var dt = new DataTable();

adapter.Fill(dt);


var command = new SqlCommand("stored procedure name")
{
    CommandType = CommandType.StoredProcedure 
};

var reader = command.ExecuteReader();
var dt = new DataTable();

dt.Load(reader);

Оба метода заполняют таблицу данных именами и типами столбцов, которые соответствуют именам и типам, возвращенным из вызова хранимой процедуры. Если вам нужна информация о схеме, вы можете получить к ней доступ через DataTable.Columns собственность.

Если вам нужно изменить схему

Если вам нужна только информация о схеме или если вам нужно манипулировать схемой в объекте DataTable перед заполнением его данными, следующий метод будет работать, даже если SqlDataAdapter.FillSchema не работает.

var command = new SqlCommand("stored procedure name")
{
    CommandType = CommandType.StoredProcedure 
};

var reader = command.ExecuteReader();

var schemaTable = reader.GetSchemaTable();

SqlDataReader.GetSchemaTable() вернет объект DataTable со столбцом метаданные заполняются в виде строк.

Вы можете перечислить результаты для создания и/или управления столбцами в объекте DataTable, который будет содержать записи, возвращаемые SqlDataReader.

В моем случае мне нужно было, чтобы каждый столбец был строкой, чтобы избежать какой-либо «помощи» форматирования из Microsoft Excel при экспорте данных в электронную таблицу. Например, мой код выглядит так:

var dt = new DataTable();

foreach(DataRow row in schemaTable.Rows)
{
    dt.Columns.Add((string)row["ColumnName"], typeof(string));
}

dt.Load(reader);
person Bobby    schedule 19.06.2018

Хранимые процедуры и временные таблицы обычно плохо сочетаются со строго типизированными реализациями объектов базы данных.

Если вы измените свою таблицу #temp на таблицу @variable, это должно решить вашу проблему.

Пример того, как перейти от временной таблицы к табличной переменной, будет выглядеть так:

    CREATE TABLE #tempTable (ID INT, Val VARCHAR(50))

to

    DECLARE @tempTable TABLE(ID INT, Val VARCHAR(50))
person Nikhil Bandivan    schedule 30.05.2019

Если вам не нужен DataSet, а только один DataTable, вы можете использовать

DataTable dt= new DataTable();

dt.Load(cmd.ExecuteReader());

Для DataSet вы должны как минимум сообщить имена таблиц (имеется в виду число), которые возвращает SP.

DataSet ds = new DataSet();
SqlDataReader sdr = cmd.ExecuteReader();
ds.Load(sdr, LoadOption.OverwriteChanges,"Table1");
person d.popov    schedule 06.11.2013
comment
вам не понравился такой подход? - person d.popov; 17.03.2014