我有一些复杂的SQL代码,我从MSSql转换为Postgres(使用Entity Framework Core 2.1),以便在插入具有唯一索引的表时处理潜在的竞争条件。这是一个愚蠢的版本:
const string QUERY = @"
DO
$$
BEGIN
insert into Foo (Field1,Field2,Field3)
values (@value1,@value2,@value3);
EXCEPTION WHEN others THEN
-- do nothing; it's a race condition
END;
$$ LANGUAGE plpgsql;
select *
from Foo
where Field1 = @value1
and Field2 = @value2;
";
return DbContext.Foos
.FromSql(QUERY,
new NpgsqlParameter("value1", value1),
new NpgsqlParameter("value2", value2),
new NpgsqlParameter("value3", value3))
.First();
换句话说,尝试插入记录,但如果插入它的尝试导致唯一的索引违规(索引在Field1 + Field2上),并且不返回记录,则不要抛出异常。是由我或其他人创建的。
这个概念在MSSql中运行良好,使用TRY..CATCH
块。据我所知,处理Postgres异常的方法就像我在plpgsql块中所做的一样。
BUT ...
似乎plpgsql块中的变量替换不起作用。上面的代码在.First()
(序列中没有元素)上失败,当我注释掉EXCEPTION
行时,我看到了真正的问题,即:
Npgsql.PostgresException:42703:column" value1"不存在
当我使用常规Sql进行测试时,即在不使用plpgsql块的情况下执行insert
,这样可以正常工作。
那么,在plpgsql块中进行变量替换的正确方法是什么?