We are using PetaPoco as our data access tool for a SQL 2008 database. We have a problem when trying to insert/update a row on a table that has a trigger attached.
We are using PetaPoco's db.Save(object);
The error shown is: The target table 'the_table_with_a_trigger' of the DML statement cannot have any enabled triggers if the statement contains an OUTPUT clause without INTO clause.
How can we use PetaPoco to insert/update data on a table that has a trigger?
Thanks to @Eduardo Molteni, you put me on the right track to solving this. Apparently it is known issue in SQL Server 2008 R2 that the OUTPUT command in an insert will fail if the table has a trigger. However, PetaPoco automatically inserts the OUTPUT clause into the command text of any insert where the table has AutoIncrement=true.
The solution for me, (for SQL Server 2008 R2) is the following:
1) Go to the PetaPoco.DatabaseTypes.SqlServerDatabaseType.GetInsertOutputClause function
remove (comment out)
\\return String.Format(" OUTPUT INSERTED.[{0}]", primaryKeyName);
This removes the "OUTPUT" from the SQL insert statement. Now, the insert will happen on a table with a trigger. However, now PetaPoco has no way to retrieve the new primary key (identity) from the newly inserted row.
2) Go to the PetaPoco.Database.Insert function. Immediately above the line:
add a new line, so it looks like this:
The new line (which existed in PetaPoco, but wasn't being used) will allow the insert statement to retrieve the identity.
Because I'm sure I won't be the last person who encounters this...
I've adopted PetaPoco for new project, but I ran into a similar problem, but reverting to scope_identity() wasn't going to work. So I:
1) Extended the IProvider interface.
2) Added them to DatabaseProvider.cs:
3) Then SqlServerDatabaseProvider, including changing the existing OUTPUT clause:
4) Lastly, incorporated these into Database.cs:
This changes the command to use a named TABLE variable, DECLAREd in the 'Preamble', populated by the OUTPUT clause and SELECTed in the 'PostScript'.
I think
cmd.CommandText += ";\nSELECT SCOPE_IDENTITY() AS NewID;";
would be better. @@IDENTITY can give you an id generated in the trigger, not your statement.PetaPoco only creates an OUTPUT parameter in Oracle DBs to get the new AutoIncrement ID.
In the case of Sql Server, as you tagged your question, it only adds a
SELECT SCOPE_IDENTITY() AS NewID
if the table has an AutoIncrement ID.Relevant code in PetaPoco.cs:
Try turning off the AutoIncrement ID and setting it up manually to see if the problem goes away