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.
/// <summary>
/// Return an SQL expression that can be used with <seealso cref="GetInsertPostScript(string)"/>
/// and <seealso cref="GetInsertOutputClause(string)"/> to return a provider-generated value from an INSERT; typically an IDENTITY
/// column in Microsoft SQL Server.
/// </summary>
/// <param name="primaryKeyName"></param>
/// <returns></returns>
string GetInsertPreamble(string primaryKeyName);
/// <summary>
/// Return an SQL expression that can be used with <seealso cref="GetInsertPreamble(string)"/>
/// and <seealso cref="GetInsertOutputClause(string)"/> to return a provider-generated value from an INSERT; typically an IDENTITY
/// column in Microsoft SQL Server.
/// </summary>
/// <param name="primaryKeyName"></param>
/// <returns></returns>
string GetInsertPostScript(string primaryKeyName);
2) Added them to DatabaseProvider.cs:
public virtual string GetInsertPreamble(string primaryKeyName)
{
return string.Empty;
}
public virtual string GetInsertPostScript(string primaryKeyName)
{
return string.Empty;
}
3) Then SqlServerDatabaseProvider, including changing the existing OUTPUT clause:
public override string GetInsertOutputClause(string primaryKeyName)
{
return String.Format(" OUTPUT INSERTED.[{0}] into @result({0})", primaryKeyName);
}
public override string GetInsertPreamble(string primaryKeyName)
{
return string.Format("DECLARE @result TABLE({0} sql_variant); ", primaryKeyName);
}
public override string GetInsertPostScript(string primaryKeyName)
{
return string.Format("; SELECT {0} FROM @result; ", primaryKeyName);
}
4) Lastly, incorporated these into Database.cs:
...string outputClause = string.Empty;
string insertPreamble = string.Empty;
string insertPostScript = string.Empty;
if (autoIncrement)
{
insertPreamble = _provider.GetInsertPreamble(primaryKeyName, tableName);
outputClause = _provider.GetInsertOutputClause(primaryKeyName);
insertPostScript = _provider.GetInsertPostScript(primaryKeyName, tableName);
}
cmd.CommandText = string.Concat(
$"{insertPreamble}",
$"INSERT INTO {_provider.EscapeTableName(tableName)} ({(string.Join(",", names.ToArray()))})",
$"{outputClause}",
$" VALUES ({(string.Join(",", values.ToArray()))})",
$"{insertPostScript}"
) ;
if (!autoIncrement)
{....
This changes the command to use a named TABLE variable, DECLAREd in the 'Preamble', populated by the OUTPUT clause and SELECTed in the 'PostScript'.