So far, all we have done is retrieve data from the database, which although very important, is really just covering the SQL SELECT statement. In this section, we will look at two ways we might make other changes to the database. First, we will look at executing statements that do not return data, such as INSERT, UPDATE, and DELETE statements. We will then look at a different way data might be inserted into the database, which involves using an ADO.NET data adapter.
Using the NpgsqlCommand ExecuteNonQuery Method
We can very easily execute statements that don’t return data by directly using the
ExecuteNonQuery method of the NpgsqlCommand object. The Insert.cs script demonstrates how to add a new customer.
// insert.cs - insert data directly using System;
using System.Data;
using Npgsql;
public class connect {
public static void Main(String[] args) { NpgsqlConnection conn = new NpgsqlConnection(
"Server=192.168.0.3;User Id=rick;Password=password;Database=bpfinal;");
try {
conn.Open();
NpgsqlCommand cmd = new NpgsqlCommand("INSERT INTO customer(title, fname, lname, addressline, town, zipcode, phone) VALUES('Mr.', 'Simon', 'Bennett', '1 Victoria Street', 'Nicetown', 'NT4 2WS', '342 6352')", conn);
int rowsaffected = cmd.ExecuteNonQuery();
Console.Write("Rows affected {0}", rowsaffected);
}
finally { conn.Close();
} } }
In this example, we simply create a command object, as before, then execute it using the ExecuteNonQuery method. We can then use the return value to check that the correct numbers of rows were affected. The UPDATE and DELETE statements are carried out in the same fashion.
Using a DataAdapter
Another way we might choose to alter data in the database is to use a DataAdapter object. This object logically sits on top of the connection object, and provides data to DataSet objects that manage the actual data. Figure 18-4 shows a very simplified representation.
Figure 18-4. Relationship of some of the ADO.NET objects
The DataSet object contains many internals, but most important to us is the DataTable object (it actually can contain many table objects, but we will keep it simple here), which is itself composed of the DataRow and DataColumn objects that contain the actual data.
The insert-ds.cs script demonstrates how we can use DataAdapter and DataSet objects to insert rows into the bpfinal database. As a change, we add a new product to our catalog. Since it is quite long, and a somewhat different approach, we present the program in segments, with a brief comment preceding each section.
// insert-ds.cs - insert data via a database This first part is the same code we have seen before.
using System;
using System.Data;
using Npgsql;
public class connect {
public static void Main(String[] args) {
NpgsqlConnection conn = new NpgsqlConnection(
"Server=192.168.0.3;User Id=rick;Password=password;Database=bpfinal;");
try {
conn.Open();
Next, we create a DataSet object ready for later use.
DataSet ds = new DataSet();
Now we create a DataAdapter object using a SQL command to retrieve data from the item table, and the connection object we created earlier.
NpgsqlDataAdapter da = new NpgsqlDataAdapter
("SELECT description, cost_price, sell_price FROM item", conn);
Next, we add an INSERT command in the DataAdapter, which we are going to use to add our new row. Notice we use a parameterized query for this example.
da.InsertCommand = new NpgsqlCommand("INSERT INTO item(description, cost_price, sell_price) VALUES(:de, :cp, :sp)", conn);
Set the data type of the parameters.
da.InsertCommand.Parameters.Add(new NpgsqlParameter(":de", DbType.String));
da.InsertCommand.Parameters.Add(new NpgsqlParameter(":cp", DbType.Double));
da.InsertCommand.Parameters.Add(new NpgsqlParameter(":sp", DbType.Double));
Bind the parameters to the column names in the item table.
da.InsertCommand.Parameters[0].SourceColumn = "description";
da.InsertCommand.Parameters[1].SourceColumn = "cost_price";
da.InsertCommand.Parameters[2].SourceColumn = "sell_price";
Use our DataAdapter to populate the DataSet we created earlier.
da.Fill(ds);
Create a DataTable, as the first (and only) table in the DataSet.
DataTable dt = ds.Tables[0];
Create a new row and populate its columns.
DataRow dr = dt.NewRow();
dr["description"] = "Large Penguin";
dr["cost_price"] = 7.23;
dr["sell_price"] = 9.99;
Add the new row to our DataTable, and tell the DataAdapter to update, based on our DataSet with the new row.
dt.Rows.Add(dr);
da.Update(ds);
Last, we have the standard trailing elements of our program.
}
finally { conn.Close();
} } }
That is quite a lot more code than the previous example, but the use of DataAdapter and DataSet objects does give us a higher-level interface to the database, with access to more advanced features.