Как да получите изход от SQL Server Insert Command с повече от един ред с помощта на C# ADO.Net?

Искам да получа целия изходен първичен ключ от тази команда за вмъкване, използвайки C# ADO.Net.

Пускам това в SQL Server 2012 Studio и видях таблицата с резултатите с всички стойности, така че възможно ли е да получа тази таблица от C#?

INSERT INTO dbo.Suspension 
(pallet_position, processing_pallet_pkey, datetime_created, datetime_updated,
created_by, updated_by) 
OUTPUT INSERTED.pkey VALUES
(1, 2, '20141013 16:27:25.000', '20141013 16:27:25.000', 2, 2), 
(2, 2, '20141013 16:27:25.000', '20141013 16:27:25.000', 2, 2), 
(3, 2, '20141013 16:27:25.000', '20141013 16:27:25.000', 2, 2), 
(4, 2, '20141013 16:27:25.000', '20141013 16:27:25.000', 2, 2);

Какво опитах в C# ADO.NET. Но DataTable не получи никаква стойност от insertedOutput.

SqlCommand cmd = new SqlCommand(insertQuery, this.conn);
var insertedOutput = cmd.ExecuteReader(); 

DataTable dt = new DataTable();
dt.Load(insertedOutput); // something wrong here

Отбелязах, че копирах SQL кода от дебъгера. Работи добре. (не съм сигурен откъде идва „това“, но не е причинило проблеми)

В програмата за отстраняване на грешки има резултати от cmd.ExecuteReader() във insertedOutput, но не мога да копирам тези резултати от dt (променлива на DataTable).


person gentlerainsky    schedule 13.10.2014    source източник
comment
// this cause an error. ‹=== какво казва грешката?   -  person Marc Gravell    schedule 13.10.2014
comment
Съжалявам, че изгубих коментара за грешката. изглежда, че dt.Load не получава стойността от insertedOutput. (но няма грешка при компилиране)   -  person gentlerainsky    schedule 13.10.2014
comment
този sql израз дори не изглежда легален (this.created_by и т.н.) - можете ли да потвърдите какво се случва там?   -  person Marc Gravell    schedule 13.10.2014
comment
Да, пробвал съм го в SQL Server Management Studio. Сега основният проблем е, че не мога да получа стойността от dt.Load(insertedOutput).   -  person gentlerainsky    schedule 13.10.2014


Отговори (2)


Заявката ви изглежда добре (с изключение на this.created_by / this.updated_by, което ме обърква, но... ако кажете, че работи...)

Първоначалната ми мисъл следователно е: може би имате тригер вместо, който неправилно обработва само един ред? Въпреки че бих очаквал това да докладва:

Целевата таблица 'dbo.Suspension' на DML оператора не може да има активирани тригери, ако операторът съдържа клауза OUTPUT без клауза INTO.

Следните 3 начина за четене на този sql (или много подобна негова версия) работят добре:

using (var conn = new SqlConnection(connectionString))
{
    conn.Open();
    const string insertQuery = @"
INSERT INTO dbo.Suspension
(pallet_position, processing_pallet_pkey, datetime_created, datetime_updated,
[this.created_by], [this.updated_by]) 
OUTPUT INSERTED.pkey VALUES
(1, 2, '20141013 16:27:25.000', '20141013 16:27:25.000', 2, 2), 
(2, 2, '20141013 16:27:25.000', '20141013 16:27:25.000', 2, 2), 
(3, 2, '20141013 16:27:25.000', '20141013 16:27:25.000', 2, 2), 
(4, 2, '20141013 16:27:25.000', '20141013 16:27:25.000', 2, 2);";

    // via datatable
    DataTable dt = new DataTable();
    using (SqlCommand cmd = new SqlCommand(insertQuery, conn))
    using (var insertedOutput = cmd.ExecuteReader())
    {
        dt.Load(insertedOutput);
    }
    Console.WriteLine(dt.Rows.Count); // 4

    // via manual read
    var list = new List<int>();
    using (SqlCommand cmd = new SqlCommand(insertQuery, conn))
    using (var insertedOutput = cmd.ExecuteReader())
    {
        while(insertedOutput.Read())
        {
            list.Add(insertedOutput.GetInt32(0));
        }
    }
    Console.WriteLine(list.Count); // 4

    // via dapper
    var ids = conn.Query<int>(insertQuery).ToList();
    Console.WriteLine(ids.Count); // 4
}
person Marc Gravell    schedule 13.10.2014
comment
За пълнота, моят скрипт за създаване: create table Suspension (pkey int not null identity(1,1), pallet_position int, processing_pallet_pkey int, datetime_created datetime, datetime_updated datetime, [this.created_by] int, [this.updated_by] int); - person Marc Gravell; 13.10.2014
comment
Благодаря ви за възможността, сега работи с DataTable, наистина не разбирам защо не работи вчера. И от трите начина, бихте ли ми казали кой е препоръчителен. Като един от изтритите отговори в тази публикация, който не знам кой го е публикувал, се казва, че това (DataTable) не е най-добрият начин. - person gentlerainsky; 14.10.2014
comment
@gentlerainsky изтритият отговор всъщност беше от мен - но се основаваше на неправилно разбиране на въпроса. Така че ще повторя предишното си мнение, че DataTable не е чудесен начин за четене на няколко цели числа (всъщност рядко използвам DataTable). Кодът за ръчно четене е достатъчно прост, но в крайна сметка пишете много от тези неща - което е защо написах dapper - свободно достъпен високопроизводителен инструмент за достъп до данни; като от последния пример, цялото това нещо става един ред. Така че да, бих използвал това ;p nuget.org/packages/Dapper - person Marc Gravell; 14.10.2014

@alecxe, моля, вижте актуализирания ми въпрос
person Satyajit    schedule 13.10.2014