2

I want to receive all output primary key from this insert command using C# ADO.Net.

I run this in SQL Server 2012 Studio and I saw the result table with all of the values, so is it possible to get that table from 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);

What I have tried in C# ADO.NET. But DataTable didn't get any value from the insertedOutput.

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

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

Noted that I copied the SQL code from the debugger. It work fine. (not sure where the 'this.' come from but it didn't cause any issues)

In the debugger, there are results from cmd.ExecuteReader() in insertedOutput, but I can't copy those result from dt (a DataTable variable).

4
  • 1
    // this cause an error. <=== what does the error say? Commented Oct 13, 2014 at 9:56
  • Sorry I misplace the error comment. it seems that dt.Load doesn't get the value from insertedOutput. (but no compile error) Commented Oct 13, 2014 at 10:01
  • that sql statement doesn't even look legal (the this.created_by etc) - can you confirm what is happening there? Commented Oct 13, 2014 at 10:07
  • Yes, I have tried it in SQL Server Management Studio. Now the main problem is that I can't get the value from dt.Load(insertedOutput). Commented Oct 13, 2014 at 10:10

2 Answers 2

3

Your query looks fine (except for the this.created_by / this.updated_by, which is confusing me, but... if you say it works...)

My initial thought, therefore, is: do you perhaps have an instead-of trigger that incorrectly only processes one row? Although I would expect that to report:

The target table 'dbo.Suspension' of the DML statement cannot have any enabled triggers if the statement contains an OUTPUT clause without INTO clause.

The following 3 ways of reading that sql (or a very similar version to it) all work fine:

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
}
Sign up to request clarification or add additional context in comments.

3 Comments

For completeness, my create script: 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);
Thank for your afford, it works now with the DataTable, I don't really understand why it didn't work yesterday. Fron all the three ways, could you tell me which one is recommended. As one of the deleted answer in this post which I don't know who post it say that this (DataTable) isn't the best way.
@gentlerainsky the deleted answer was actually by me - but it was based on an incorrect understanding of the question. So I will echo my earlier opinion that DataTable is not a great way to read a few integers (actually, I rarely use DataTable at all). The "manual read" code is simple enough, but you end up writing a lot of that stuff - which is why I wrote "dapper" - a freely available high-performance data access tool; as from the last example, this entire thing becomes one line. So yeah, I'd use that ;p nuget.org/packages/Dapper
0

You can use the value of the identity column in the inserted row and store it in a table then fetch the values from it.

DECLARE @tblIds TABLE (id int)

Insert into dbo.Suspension 
(pallet_position, processing_pallet_pkey, datetime_created, datetime_updated,
created_by, updated_by)
OUTPUT inserted.pkey INTO @tblIds
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)

select * from @tblIds

Here i am assuming pkey is your identity column :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.