如何使用ADO.NET?

时间:2017-03-30 07:12:08

标签: c# sql postgresql ado.net npgsql

给出如下表格:

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?

0 个答案:

没有答案