Reputation: 732
I'm trying to use the NpgsqlCommandBuilder to automatically generate SQL commands to perform insert/update/delete operations on a dataset. The dataset will be bound to a datagrid (which I really don't know how to do yet). So I will not be manually editing the data set. When trying to automatically generate the sql commands, it will throw an exception when calling NpgsqlDataAdaptor.Update()
Here is the schema for the db table:
tblFee
{
character(4) dest,
character(4) id,
character(2) indicator,
double fee
}
the primary key is (dest, id, indicator)
Here is my code:
string m_strConnection = "Server=192.168.253.20;Port=5432;User Id=alex;Password=asdf;Database=mydb;";
DataSet m_ds = new DataSet("EcnFeeData");
NpgsqlConnection m_conn = new NpgsqlConnection(m_strConnection);
NpgsqlDataAdapter m_dAdapter = new NpgsqlDataAdapter();
m_dAdapter.SelectCommand = new NpgsqlCommand("SELECT * FROM \"tblFee\"", m_conn);
NpgsqlCommandBuilder builder = new NpgsqlCommandBuilder(m_dAdapter);
m_conn.Open();
m_dAdapter.Fill(m_ds, "tblFee");
m_ds.Tables[0].Rows[0]["fee"] = 1;
builder.GetUpdateCommand();
m_dAdapter.Update(m_ds, "tblFee");
This exception will get thrown while the last line is executing:
A first chance exception of type 'System.InvalidOperationException' occurred in System.Data.dll
Additional information: Update requires a valid UpdateCommand when passed DataRow collection with modified rows.
The same thing happens when trying to insert a row, only the exception message is different:
Additional information: Update requires a valid InsertCommand when passed DataRow collection with new rows.
The last code example was an attempt to use the NpgsqlCommandBuilder the same way the SqlCommandBuilder is used in the example that is provided by the .NET 4.0 documentation. The Npgsql documentation does not provide an example to do it this way. Is this feature not supported in NpgsqlCommandBuilder? I'd prefer to have the NpgsqlCommandBuilder automatically generate the sql commands, but if it doesn't work then I'll have to manually create them.
After following the example in the Npgsql documentation for manually generating the InsertCommand, I was able to get it working, but I could not figure out how to do this for the UpdateCommand. Here is the code I used to create the InsertCommand:
m_dAdapter.InsertCommand = new NpgsqlCommand("insert into \"tblFee\" (dest, id, indicator, fee) values (:a, :b, :c, :d)", m_conn);
m_dAdapter.InsertCommand.Parameters.Add(new NpgsqlParameter("a", DbType.AnsiStringFixedLength));
m_dAdapter.InsertCommand.Parameters.Add(new NpgsqlParameter("b", DbType.AnsiStringFixedLength));
m_dAdapter.InsertCommand.Parameters.Add(new NpgsqlParameter("c", DbType.AnsiStringFixedLength));
m_dAdapter.InsertCommand.Parameters.Add(new NpgsqlParameter("d", DbType.Double));
m_dAdapter.InsertCommand.Parameters[0].Direction = ParameterDirection.Input;
m_dAdapter.InsertCommand.Parameters[1].Direction = ParameterDirection.Input;
m_dAdapter.InsertCommand.Parameters[2].Direction = ParameterDirection.Input;
m_dAdapter.InsertCommand.Parameters[3].Direction = ParameterDirection.Input;
m_dAdapter.InsertCommand.Parameters[0].SourceColumn = "dest";
m_dAdapter.InsertCommand.Parameters[1].SourceColumn = "id";
m_dAdapter.InsertCommand.Parameters[2].SourceColumn = "indicator";
m_dAdapter.InsertCommand.Parameters[3].SourceColumn = "fee";
m_dAdapter.InsertCommand.Connection = m_conn;
Here is my attempt to do the UpdateCommand, which doesn't work:
m_dAdapter.UpdateCommand = new NpgsqlCommand("update \"tblFee\" set dest = :a, id = :b, indicator = :c, fee = :d where dest = :e and id = :f and indicator = :g");
m_dAdapter.UpdateCommand.Parameters.Add(new NpgsqlParameter("a", DbType.AnsiStringFixedLength));
m_dAdapter.UpdateCommand.Parameters.Add(new NpgsqlParameter("b", DbType.AnsiStringFixedLength));
m_dAdapter.UpdateCommand.Parameters.Add(new NpgsqlParameter("c", DbType.AnsiStringFixedLength));
m_dAdapter.UpdateCommand.Parameters.Add(new NpgsqlParameter("d", DbType.Double));
m_dAdapter.UpdateCommand.Parameters.Add(new NpgsqlParameter("e", DbType.AnsiStringFixedLength));
m_dAdapter.UpdateCommand.Parameters.Add(new NpgsqlParameter("f", DbType.AnsiStringFixedLength));
m_dAdapter.UpdateCommand.Parameters.Add(new NpgsqlParameter("g", DbType.AnsiStringFixedLength));
m_dAdapter.UpdateCommand.Parameters[0].Direction = ParameterDirection.Input;
m_dAdapter.UpdateCommand.Parameters[1].Direction = ParameterDirection.Input;
m_dAdapter.UpdateCommand.Parameters[2].Direction = ParameterDirection.Input;
m_dAdapter.UpdateCommand.Parameters[3].Direction = ParameterDirection.Input;
m_dAdapter.UpdateCommand.Parameters[4].Direction = ParameterDirection.Input;
m_dAdapter.UpdateCommand.Parameters[5].Direction = ParameterDirection.Input;
m_dAdapter.UpdateCommand.Parameters[6].Direction = ParameterDirection.Input;
m_dAdapter.UpdateCommand.Parameters[0].SourceColumn = "dest";
m_dAdapter.UpdateCommand.Parameters[1].SourceColumn = "id";
m_dAdapter.UpdateCommand.Parameters[2].SourceColumn = "indicator";
m_dAdapter.UpdateCommand.Parameters[3].SourceColumn = "fee";
m_dAdapter.UpdateCommand.Parameters[4].SourceColumn = "dest_orig";
m_dAdapter.UpdateCommand.Parameters[5].SourceColumn = "id_orig";
m_dAdapter.UpdateCommand.Parameters[6].SourceColumn = "indicator_orig";
m_dAdapter.UpdateCommand.Connection = m_conn;
Any help would be much appreciated.
Alex
Upvotes: 1
Views: 3482
Reputation: 1
To use the NpgsqlCommandBuilder you need to:
m_dAdapter.InsertCommand = builder.GetInsertCommand(m_ds.Tables[0].Rows[0]);
m_dAdapter.UpdateCommand = builder.GetUpdateCommand(m_ds.Tables[0].Rows[0]);
m_dAdapter.DeleteCommand = builder.GetDeleteCommand(m_ds.Tables[0].Rows[0]);
Try it and let us know if it works for you. In fact I do not know why SqlCommandBuilder works for you if you do not indicate to what adapter associate the commands.
Upvotes: 0
Reputation: 113342
You can set and manipulate the NpgsqlDataAdapter
's UpdateCommand
just as you have it's InsertCommand
above.
As well as the documentation at http://npgsql.projects.postgresql.org/docs/api/Npgsql.NpgsqlDataAdapterMembers.html it works analogously to SqlDataAdapter, so the example at http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldataadapter.updatecommand.aspx will be worth a look.
Upvotes: 1