给出如下表格:
CREATE TABLE myTable (
identity SERIAL PRIMARY KEY,
foo VARCHAR(32) NOT NULL
)
我想使用ADO.NET在该表上执行UPSERT,我在C#中的POCO看起来像:
public class myEntity {
//When null the entity has never been stored in the database
public int? Identity { get; set; }
public string Foo { get; set; }
}
我想出了以下用于DbCommand
的查询INSERT INTO myTable (identity, foo) VALUES (@identity, @foo)
ON CONFLICT (identity) DO UPDATE SET
foo = @foo
RETURNING identity;
DbCommand初始化如下
using (var dbCommand = new NpgsqlCommand(INSERT_QUERY, dbConnection))
{
dbCommand.Parameters.AddWithValue("@identity", oneOfMyEntities.Identity);
dbCommand.Parameters.AddWithValue("@foo", oneOfMyEntities.Foo);
int idReturned = (int)await dbCommand.ExecuteScalar();
if (!oneOfMyEntity.Identity.HasValue) oneOfMyEntity.Identity = idReturned;
}
我想要实现的是,当 myEntity 的实例将属性Identity设置为 null 时,会将新行插入到数据库中,并使用序列,否则执行更新。
问题是在PostgreSQL中“强制”使用序列中下一个值的唯一方法是从INSERT查询中省略标识列或使用DEFAULT。我不能简单地将文字“DEFAULT”放在dbCommand参数@identity中,因为据我所知,这将被解释为字符串值而不是关键字DEFAULT。
我试图在运行时生成查询文本,这样如果实体没有标识,我用@ DEFAULT替换@identity参数,但这对我来说不太好看,因为我可以简单地删除ON CONFLICT,两个查询(一个INSERT和一个UPDATE)并执行INSERT或UPDATE,具体取决于实体标识是否为空,因此不利用ON CONFLICT子句。
如何编写这个逻辑,以便当一个实体作为一个空身份我可以某种方式“强迫”PostgreSQL使用序列中的下一个值,而不需要在运行时生成查询文本(并用@identity参数替换DEFAULT)或根据具体情况单独使用UPDATE或INSERT?