因为我确定我不会是最后一个遇到这种情况的人......
我在新项目中采用了 PetaPoco,但我遇到了类似的问题,但恢复到 scope_identity() 是行不通的。所以我:
1) 扩展了 IProvider 接口。
/// <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) 将它们添加到 DatabaseProvider.cs:
public virtual string GetInsertPreamble(string primaryKeyName)
{
return string.Empty;
}
public virtual string GetInsertPostScript(string primaryKeyName)
{
return string.Empty;
}
3)然后是SqlServerDatabaseProvider,包括改变现有的OUTPUT子句:
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) 最后,将这些合并到 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)
{....
这会将命令更改为使用命名的 TABLE 变量,在“Preamble”中声明,由 OUTPUT 子句填充并在“PostScript”中选择。