-
Oct 27th, 2008, 12:38 AM
#1
Retrieving and Saving Data in Databases
VB version here.
There is all sorts of literature on this topic but people still keep asking the same questions. I'm creating this thread so I can send people here to look at some example code that I know will demonstrate all the principles they need. These principles can be extended or adjusted and applied to any data access situation. This code uses members of the System.Data.SqlClient namespace. If you're not using SQL Server then it's a simple matter of switching to the corresponding types of the appropriate namespace for your data source. For example, if you're using an Access database then you'd use an OleDb.OleDbConnection rather than an SqlClient.SqlConnection.
Retrieving a single value. The ExecuteScalar method returns the value from the first column of the first row of the query's result set:
CSharp Code:
using (SqlConnection connection = new SqlConnection("connection string here")) using (SqlCommand command = new SqlCommand("SELECT SUM(Quantity) FROM StockItem", connection)) { connection.Open(); double totalQuantity = (double)command.ExecuteScalar(); }
Retrieving multiple records that will be read and discarded. The ExecuteReader method provides read-only, forward-only access to the entire result set:
CSharp Code:
using (SqlConnection connection = new SqlConnection("connection string here")) using (SqlCommand command = new SqlCommand("SELECT Quantity, Unit, Name FROM StockItem", connection)) { connection.Open(); using (SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { MessageBox.Show(String.Format("There are {0} {1} of {2} remaining in stock.", reader["Quantity"], reader["Unit"], reader["Name"])); } } }
Retrieving multiple records for display that will not be updated. The DataTable.Load method will populate a DataTable with the result set exposed by a DataReader:
CSharp Code:
using (SqlConnection connection = new SqlConnection("connection string here")) using (SqlCommand command = new SqlCommand("SELECT Quantity, Unit, Name FROM StockItem", connection)) { connection.Open(); using (SqlDataReader reader = command.ExecuteReader()) { DataTable table = new DataTable(); table.Load(reader); // The table can be used here to display the data. // That will most likely be done via data-binding but that is NOT a data access issue. } }
Retrieving multiple records for display and editing, then saving the changes. The DataAdapter.Fill method populates a DataTable with the contents of the result set of a query. The DataAdapter.Update method saves the changes in a DataTable in accordance with the SQL statements contained in the DeleteCommand, InsertCommand and UpdateCommand properties:
CSharp Code:
private SqlConnection connection = new SqlConnection("connection string here"); private SqlDataAdapter adapter; private DataTable table = new DataTable(); private void InitialiseDataAccessObjects() { this.adapter = new SqlDataAdapter("SELECT ID, Name, Quantity, Unit FROM StockItem", this.connection); SqlCommand delete = new SqlCommand("DELETE FROM StockItem WHERE ID = @ID", this.connection); SqlCommand insert = new SqlCommand("INSERT INTO StockItem (Name, Quantity, Unit) VALUES (@Name, @Quantity, @Unit)", this.connection); SqlCommand update = new SqlCommand("UPDATE StockItem SET Name = @Name, Quantity = @Quantity, Unit = @Unit WHERE ID = @ID", this.connection); delete.Parameters.Add("@ID", SqlDbType.Int, 4, "ID"); insert.Parameters.Add("@Name", SqlDbType.VarChar, 100, "Name"); insert.Parameters.Add("@Quantity", SqlDbType.Float, 8, "Quantity"); insert.Parameters.Add("@Unit", SqlDbType.VarChar, 10, "Unit"); update.Parameters.Add("@Name", SqlDbType.VarChar, 100, "Name"); update.Parameters.Add("@Quantity", SqlDbType.Float, 8, "Quantity"); update.Parameters.Add("@Unit", SqlDbType.VarChar, 10, "Unit"); update.Parameters.Add("@ID", SqlDbType.Int, 4, "ID"); this.adapter.DeleteCommand = delete; this.adapter.InsertCommand = insert; this.adapter.UpdateCommand = update; this.adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey; } private void GetData() { // Retrieve the data. this.adapter.Fill(this.table); // The table can be used here to display and edit the data. // That will most likely involve data-binding but that is not a data access issue. } private void SaveData() { // Save the data. this.adapter.Update(this.table); }
Note that if your query involves only one table and it has a primary key then you can take the easy option and use a CommandBuilder instead of creating the non-query commands yourself:
CSharp Code:
private SqlConnection connection = new SqlConnection("connection string here"); private SqlDataAdapter adapter; private SqlCommandBuilder builder; private DataTable table = new DataTable(); private void InitialiseDataAccessObjects() { this.adapter = new SqlDataAdapter("SELECT ID, Name, Quantity, Unit FROM StockItem", this.connection); this.builder = new SqlCommandBuilder(this.adapter); this.adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey; } private void GetData() { // Retrieve the data. this.adapter.Fill(this.table); // The table can be used here to display and edit the data. // That will most likely involve data-binding but that is not a data access issue. } private void SaveData() { // Save the data. this.adapter.Update(this.table); }
Saving changes directly to one or more records in the database. The Command.ExecuteNonQuery method will execute any SQL statement and not return a result set. It can be used to execute a query but you'd never use it for that unless you were populating a view or temp table. Usually you'd use ExecuteNonQuery to execute a DELETE, INSERT or UPDATE command:
CSharp Code:
using (SqlConnection connection = new SqlConnection("connection string here")) using (SqlCommand command = new SqlCommand("INSERT INTO StockItem (Name, Quantity, Unit) VALUES (@Name, @Quantity, @Unit)", connection)) { command.Parameters.AddWithValue("@Name", someName); command.Parameters.AddWithValue("@Quantity", someQuantity); command.Parameters.AddWithValue("@Unit", someUnit); connection.Open(); command.ExecuteNonQuery(); }
Last edited by jmcilhinney; Jan 17th, 2019 at 06:18 PM.
-
Oct 27th, 2008, 12:43 AM
#2
Re: Retrieving and Saving Data in Databases
Inserting multiple records into a table. This situation is much like the fourth example above, except you don't need to retrieve any data to start with and you obviously don't need the UpdateCommand and DeleteCommand:
CSharp Code:
using (SqlConnection connection = new SqlConnection("connection string here")) using (SqlDataAdapter adapter = new SqlDataAdapter("SELECT ID, Name, Quantity, Unit FROM StockItem", connection)) { SqlCommand insert = new SqlCommand("INSERT INTO StockItem (Name, Quantity, Unit) VALUES (@Name, @Quantity, @Unit)", connection); insert.Parameters.Add("@Name", SqlDbType.VarChar, 100, "Name"); insert.Parameters.Add("@Quantity", SqlDbType.Float, 8, "Quantity"); insert.Parameters.Add("@Unit", SqlDbType.VarChar, 10, "Unit"); adapter.InsertCommand = insert; adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey; DataTable table = new DataTable(); // Retrieve the data. adapter.FillSchema(table, SchemaType.Source); // Add the new rows to the DataTable, e.g. DataRow row = table.NewRow(); row["Name"] = someName; row["Quantity"] = someQuantity; row["Unit"] = someUnit; table.Rows.Add(row); // Save the changes. adapter.Update(table); }
I should also point out that you don't actually need the SelectCommand and the FillSchema call either. You can simply build the DataTable schema yourself if you like.
Last edited by jmcilhinney; Jan 17th, 2019 at 06:28 PM.
-
Nov 8th, 2008, 07:58 PM
#3
Re: Retrieving and Saving Data in Databases
Note that I have updated the code examples above to more accurately reflect real usage situations, particularly using a DataAdapter to get and save data in separate methods rather than in the same method.
-
Apr 5th, 2012, 08:42 AM
#4
New Member
Re: Retrieving and Saving Data in Databases
I am trying to similar to your code "Retrieving multiple records for display and editing, then saving the changes." but my table does not seem to be updating.
Code:
public void update(string command, string update, string table)
{
SqlConnection conn = new SqlConnection(conStr);
SqlDataAdapter adapter = new SqlDataAdapter();
DataTable dt = new DataTable();
adapter = new SqlDataAdapter(command, conn);
SqlCommand updateCommand = new SqlCommand(update, conn);
adapter.UpdateCommand = updateCommand;
adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;
adapter.Fill(dt);
adapter.Update(dt);
}
-
Apr 5th, 2012, 10:19 AM
#5
Re: Retrieving and Saving Data in Databases
I'm not sure what exactly you expect to happen but you're not editing any of the data you retrieve so there are no changes to save. What's the point of retrieving data and then immediately saving it? How can it contain changes if you only just retrieved it?
-
Apr 5th, 2012, 10:43 AM
#6
New Member
Re: Retrieving and Saving Data in Databases
How would you suggest doing approaching it then? As i cant use a command builder and im updating to a view?
this is where im calling the function
Code:
if (txtNew.Text == txtConfirmNew.Text)
{
select = "Select * from staff";
update = @"UPDATE staff SET password = '" + txtNew.Text + "'" +
"where staff_No = '" + Global.staffID + "'";
dc.update(select, update, "staff");
MessageBox.Show("Password Changed");
}
-
Apr 5th, 2012, 10:52 AM
#7
Re: Retrieving and Saving Data in Databases
I suggest that you do it the why I've shown it be done. You retrieve the data, then you edit it, then you save it. Fill retrieves the data and Update saves it, so those two method calls have to be separated, with the editing in between.
-
Apr 5th, 2012, 12:27 PM
#8
New Member
Re: Retrieving and Saving Data in Databases
Ok so this is what im trying -
Code:
private SqlConnection connect;
private SqlDataAdapter da;
private DataTable dt;
string conStr = "Data Source=.\\SQLEXPRESS;AttachDbFilename=|DataDirectory|\\NTO.mdf;Integrated Security=True;User Instance=True";
public void Fill(string command, string update, string table)
{
connect = new SqlConnection(conStr);
connect.Open();
da = new SqlDataAdapter();
SqlCommand sqlCommand = new SqlCommand(command, connect);
da.SelectCommand = sqlCommand;
sqlCommand = new SqlCommand(update, connect);
da.UpdateCommand = sqlCommand;
dt = new DataTable(table);
da.Fill(dt);
}
public void Update()
{
if (da != null) da.Update(dt);
}
public void CloseConnection()
{
if (da != null && connect != null)
{
da.Dispose();
da = null;
connect.Close();
connect = null;
}
}
I am calling this functions in this order
Code:
if (txtNew.Text == txtConfirmNew.Text)
{
select = "Select * from staff";
update = @"UPDATE staff SET password = '" + txtNew.Text + "'" +
"where staff_No = '" + Global.staffID + "'";
dc.Fill(select, update, "staff");
}
Code:
private void button2_Click(object sender, EventArgs e)
{
dc.Update();
MessageBox.Show("updated");
}
Code:
private void btnMenu_Click(object sender, EventArgs e)
{
MainMenu menu = new MainMenu();
this.Hide();
menu.Show();
dc.CloseConnection();
}
And still no data being updated
-
Apr 5th, 2012, 09:55 PM
#9
Re: Retrieving and Saving Data in Databases
What value does your call to Update return?
-
Jun 30th, 2018, 10:10 AM
#10
Addicted Member
Re: Retrieving and Saving Data in Databases
Code:
private void GetData()
{
// Retrieve the data.
this.adapter.Fill(this.dataTable);
// The table can be used here to display and edit the data.
// That will most likely involve data-binding but that is not a data access issue.
}
private void SaveData()
{
// Save the data.
this.adapter.Update(this.RaiseDragEvent); // It displays error at this line
}
Hi I'm getting error: Cannot convert from 'method group' to 'DataSet'
I'm not a man of too many faces
The mask I wear is one
-
Jun 30th, 2018, 10:20 AM
#11
Addicted Member
Re: Retrieving and Saving Data in Databases
Anyway I had duplicate code I removed them.
I'm not a man of too many faces
The mask I wear is one
-
Jun 30th, 2018, 10:26 AM
#12
Re: Retrieving and Saving Data in Databases
Originally Posted by nikel
Code:
private void GetData()
{
// Retrieve the data.
this.adapter.Fill(this.dataTable);
// The table can be used here to display and edit the data.
// That will most likely involve data-binding but that is not a data access issue.
}
private void SaveData()
{
// Save the data.
this.adapter.Update(this.RaiseDragEvent); // It displays error at this line
}
Hi I'm getting error: Cannot convert from 'method group' to 'DataSet'
If you populate 'this.dataTable' when you call Fill, where do you think you should be saving changes from when you call Update?
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|