2015-08-22 30 views
2

我使用PostgreSQL和ADO.NET NpgSQL。当我刚刚开始使用PostgreSQL和NpgSQL时,请原谅这个问题的简单性。PostgreSQL参数化插入与ADO.NET

像这样工作得很好:

[Test] 
public void InsertNoParameters() 
{ 
    NpgsqlConnection conn = new NpgsqlConnection("Host=localhost; Database=postgres; User ID=postgres; Password=password"); 
    conn.Open(); 

    IDbCommand command = conn.CreateCommand(); 
    string sql = "INSERT INTO Customers (FirstName,LastName) VALUES ('Test','Tube')"; 
    command.CommandText = sql; 
    command.ExecuteNonQuery(); 
    conn.Close(); 
} 

当我把参数我得到的错误信息: Npgsql.NpgsqlException:错误:42703:列 “_FirstName” 不存在

[Test] 
public void InsertWithParameters() 
{ 
NpgsqlConnection conn = new NpgsqlConnection("Host=localhost; Database=postgres; User ID=postgres; Password=password"); 
conn.Open(); 

IDbCommand command = conn.CreateCommand(); 
string sql = "INSERT INTO Customers (FirstName,LastName) VALUES (_FirstName,_LastName)"; 
command.CommandText = sql; 

var parameter = command.CreateParameter(); 
parameter.ParameterName = "_FirstName"; 
parameter.Value = "Test"; 
command.Parameters.Add(parameter); 

parameter = command.CreateParameter(); 
parameter.ParameterName = "_LastName"; 
parameter.Value = "Tube"; 
command.Parameters.Add(parameter); 

command.ExecuteNonQuery(); 
conn.Close(); 
} 
+0

大写<>小写。请仅使用小写字母或引用您的标识符(使用双引号)。 – wildplasser

+0

我只是试过所有的小写参数名称,我仍然得到相同的错误。 psql(或pgadmin)中的 –

+0

检查列的实际名称。 – wildplasser

回答

4

评论中的回复是正确的:

  1. Npgsql不支持_作为参数ameter占位符符号。你应该使用@或:(so @FirstName或:FirstName,而不是_FirstName)。
  2. PostgreSQL会自动小写你的表名和列名,除非它们是双引号。在所有内容中使用小写名称(简单)或在SQL查询中引用标识符。

所以,你的代码看起来应该或多或少是这样的:

IDbCommand command = conn.CreateCommand(); 
string sql = "INSERT INTO Customers (first_name, last_name) VALUES (@FirstName,@LastName)"; 
command.CommandText = sql; 

var parameter = command.CreateParameter(); 
parameter.ParameterName = "FirstName"; 
parameter.Value = "Test"; 
command.Parameters.Add(parameter); 
+1

我不同意#2的建议。引用的标识符不应该被普遍使用。如果你定义了一个带引号的字段,每次引用该字段时都必须使用它们。所以最好是值得的(但它不会)。套管与下划线是有争议的。使用基于名称的名称在没有带引号的标识符的情况下工作得很好,有时候它更可取...取决于项目。 –

+1

如果没有带引号的标识符,使用基于名称的名字就无法正常工作,因为PostgreSQL会将名称折叠为小写。这意味着'Ident1'和'ident1'将会发生冲突。引用您的标识符没有什么特别的错 - 这是一个标准的PostgreSQL实践,并且在需要混合的情况下是必需的。例如,将C#属性名称映射到数据库列(例如实体框架)的O/RM通常会引用所有标识符。 –

+0

您可以使用套用名称发出定义查询和数据查询,它可以正常工作。 Postgres将使用它的“不区分大小写”版本来处理它们,这意味着它们将会更低。不能将较小的名称映射到案例命名的对象属性的ORM可能也会对使用下划线的其他建议有问题。创建具有带引号标识符的列的ORM创建了一个债务,用户将来必须支付这笔债务。 –