Adding records to MS Access database through C# - c#

I am attempting to add items to an Access database in C#. I have code that seems to work (I can open and close a database), but the button click event produces errors. I have been searching on Google for the whole afternoon but no joy. My code is:
private void button26_Click(object sender, EventArgs e)
{ //Setup tab LoadDatabase
try
{
connection.Open();
button26.ForeColor = Color.Lime;
mainDataGridView.Visible = true;
OleDbCommand cmd = new OleDbCommand();
cmd.CommandText = "INSERT INTO Main('Prop', 'Value', 'Default','Type') VALUES('one', 'Kelly', 'Jill','one')";
cmd.ExecuteNonQuery();
button26.Text = "Done Insert";
connection.Close();
}
catch (Exception ex)
{
richTextBox1.Text=("Error "+ex);
button26.ForeColor = Color.Black;
connection.Close();
}
}
And the error I get is:
Error System.InvalidOperationException: ExecuteNonQuery: Connection property has not been initialized.
at System.Data.OleDb.OleDbCommand.ValidateConnection(String method)
at System.Data.OleDb.OleDbCommand.ValidateConnectionAndTransaction(String method)
? at System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior behavior, String method)
at System.Data.OleDb.OleDbCommand.ExecuteNonQuery()
at CrewCheifSettingsBeta3.Form1.button26_Click(Object sender, EventArgs e) in C:\Somepath\Form1.cs:line 49
Clearly something wrong with the connection string, and that it's not SQL-injection proof either.

The problem is well known. A command need to know the connection to use to execute the command text. However you have other problems in your code.
Connection objects (like commands) should not be global, but created when they are needed and destroyed after. The using statement is very usefull here because you don't have to explicitly close and destroy these objects and you will never have resource leaks when an exception occurs.
Second, when you use field names that are also reserved keywords in your database you should enclose these name in some kind of escape characters. These characters for Access are the open/close brackets not the single quote.
private void button26_Click(object sender, EventArgs e)
{
try
{
string cmdText = #"INSERT INTO Main
([Prop], [Value], [Default],[Type])
VALUES('one', 'Kelly', 'Jill','one')";
using(OleDbConnection connection = new OleDbConnection(.....))
using(OleDbCommand cmd = new OleDbCommand(cmdText, connection))
{
connection.Open();
cmd.ExecuteNonQuery();
button26.Text = "Done Insert";
button26.ForeColor = Color.Lime;
mainDataGridView.Visible = true;
}
}
catch (Exception ex)
{
richTextBox1.Text=("Error "+ex);
button26.ForeColor = Color.Black;
}
}
Finally I don't know if your fields are of text type. You pass literal texts so they should be of text type and remember to use parameters when you switch this simple code to your actual values.

Assign Connection property as below line.
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = connection;

Per #Steve's comment, there is no connection associated with the command when you just instantiate it like that. You need to either set the Connection property of the command or better yet use connection.CreateCommand() to create the command in the first place in which case it will already be associated with the connection (cleaner).

Related

update database using SqlDataAdapter in C#

I have below code to update my database table when button is clicked but it doesn't work.
protected void Button_Click(object sender, EventArgs e)
{
HasinReservation.Entities.Db.Transaction dt = new Transaction();
SqlConnection connection = new SqlConnection(
#"Data Source=192.x.x.x\Sql2008;Initial Catalog=GardeshgariKish;User ID=cms;Password=xxxxx;MultipleActiveResultSets=True;Application Name=EntityFramework");
connection.Open();
SqlCommand sqlCmd = new SqlCommand(
"Update Transaction SET IsCancelled = 1 WHERE BarCodeNumber = #Value1", connection);
SqlDataAdapter sqlDa = new SqlDataAdapter(sqlCmd);
string barcode = dgvData.Rows[0].Cells[12].Text;
sqlCmd.Parameters.AddWithValue("Value1", barcode);
connection.Close();
}
I am troubled by your implementation of Entity Framework but then not using the framework for what it was designed...
You have configured your data adapter and the command, and even opened the connection... but you have not actually executed the command.
sqlCmd.ExecuteNonQuery();
I understand that your actual business logic may have been replaced with this simple CRUD operation, but the main reason that we use the Entity Framework is to avoid writing any T-SQL in our business logic. Why didn't you use the framework to commit the change:
protected void Button3_Click(object sender, EventArgs e)
{
// cancel the selected transaction
string selectedBarcode = dgvData.Rows[0].Cells[12].Text;
using(var dataContext = new HasinReservation.Entities.Db())
{
var transaction = dataContext.Transaction.Single(t => t.Barcode == selectedBarcode);
transaction.IsCancelled = true;
dataContext.SaveChanges();
}
}
This in itself may not be a great solution but it uses the framework to do exactly what you attempted to do manually.
Why are you trying to use a SqlDataAdapter to execute an UPDATE statement? When constructing a SqlDataAdapter with a SqlCommand object, that command object represents the SELECT command for the adapter. An UPDATE statement doesn't select anything, and a SELECT command doesn't update anything.
Get rid of the SqlDataAdapter entirely and just execute the command:
sqlCmd.ExecuteNonQuery();
You'll probably also want to add some error handling so exceptions don't reach the UI (and to ensure the connection is properly closed on error conditions). You also don't seem to be doing anything with that Transaction object, so you can probably get rid of that too.

MSAccess database update not updating using c#

I am making a database system. I've implemented the INSERT function properly but when I tried implementing the UPDATE function, I couldn't make any changes to the database. I don;t know where I went wrong.
Note: username is declared as string
Here is the function handling the UPDATE:
private void btnUpdate_Click(object sender, EventArgs e)
{
string q = "UPDATE [registrationinfo] SET [Password]='?', [EmailAdd]='?', [HomeAdd]='?' WHERE [Username]='?'";
OleDbConnection connect = new OleDbConnection(MyConnectionString);
connect.Open();
try
{
OleDbCommand command = new OleDbCommand(q,connect);
command.Parameters.AddWithValue("#Password", txt_password.Text);
command.Parameters.AddWithValue("#EmailAdd", txt_eadd.Text);
command.Parameters.AddWithValue("#HomeAdd", txt_homeadd.Text);
command.Parameters.AddWithValue("Username", username);
command.ExecuteNonQuery();
txt_password.Clear();
txt_eadd.Clear();
txt_homeadd.Clear();
txt_conPass.Clear();
}
catch (Exception ex)
{
connect.Close();
MessageBox.Show(ex.Message.ToString());
}
connect.Close();
}
When using a parameterized query you do not need to put single quotes (') around text parameters in your CommandText, so you should be using something like this:
string q = "UPDATE [registrationinfo] SET [Password]=?, [EmailAdd]=?, [HomeAdd]=? WHERE [Username]=?";

SQL server express, cannot read or write in C#

I have a code written that automatically adds and reads information from my SQL Server 2012 Express table, Logins. But it wont work, here is the code:
private void Form1_Load(object sender, EventArgs e)
{
SqlConnection myConnection = new SqlConnection("user id=myComputer;" + "server=MYCOMPUTER-PC\\SQLEXPRESS;" +
"Trusted_Connection=yes;" + "database=loginTest; " + "connection timeout=5");
try
{
myConnection.Open();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
SqlCommand myCommand = new SqlCommand("INSERT INTO dbo.Logins Values ('John','Password','Admin')", myConnection);
try
{
SqlDataReader myReader = null;
SqlCommand myCommand1 = new SqlCommand("select * from Logins",
myConnection);
myReader = myCommand1.ExecuteReader();
while (myReader.Read())
{
MessageBox.Show(myReader["Column1"].ToString());
MessageBox.Show(myReader["Column2"].ToString());
}
}
catch (Exception ex1)
{
MessageBox.Show(ex1.ToString());
}
}
I have debugged the program and it all seems to go through fine, it skips over :
{
MessageBox.Show(myReader["Column1"].ToString());
MessageBox.Show(myReader["Column2"].ToString());
}
for some reason, and it doesnt write the values i told it to.
Can anyone tell me why? Im a beginner at SQL, so go easy please :)
PS It doesnt fire out any error codes or exceptions
You Logins table doesn't have any records, if you mean you want to try inserting some record first to test, it's this line causing your problem:
SqlCommand myCommand = new SqlCommand("INSERT INTO dbo.Logins Values ('John','Password','Admin')", myConnection);
myCommand.ExecuteNonQuery();//Do this to insert something into your Logins first.
it skips over [...]
Presumably that's because there's no data to read, so myReader.Read() just returns false.
it doesnt write the values i told it to.
You don't actually tell it to write anything. You create a SqlCommand to insert data, but you never execute it. You need to use myCommand.ExecuteNonQuery. You should also use using statements for the commands, the connection and the reader, to make sure they get closed properly.

using winforms to insert data in sql database , drawback of opening connection frequently

I am developing a front-end sales application.
Is this an efficient way of inserting data multiple times into a sql table, from a single button:
private void button1_Click(object sender, EventArgs e)
{
c.Open();
string w = "insert into checkmultiuser(username) values (#username)";
SqlCommand cmd = new SqlCommand(w, c);
cmd.Parameters.Add("#username", SqlDbType.VarChar);
cmd.Parameters["#username"].Value = textBox1.Text;
//cmd.ExecuteNonQuery();
cmd.ExecuteReader();
c.Close();
}
What are its drawbacks? One would be that again and again the connection is opened and closed when the button is clicked which would effect the speed greatly.
You ar edoing the right way: see this question: to close connection to database after i use or not? too.
Perhaps don't do the database insert for each entry, but store each entry in a DataSet, then insert them all at once, a la a save button.
For each entry do this:
String s = textBox1.Text;
If ( *\Enter validation logic*\ )
{
//Insert data into DataSet
}
else
{
//Throw error for user.
}
Then once you're ready to commit to DB, insert each item from the DataSet, similar to the examples in the other answers here.
I would open the connection once when the form opens and re-use that connection until the form is closed.
As for inserting records, the code you have is right.
From a resource management point of view it would be better if you can work out how many times you need to insert the data and then perform the operation in the one button click, perhaps iterating through a loop until the correct amount of insert operations has been completed. This means you are not constantly opening and closing the connection with each button press but instead opening it, performing the insert queries and closing the connection.
Also I recommend that you implement your code with the "using" statement, this way it will automatically handle the disposal and release of resources.
private void button1_Click(object sender, EventArgs e, string[] value)
{
try
{
using(SQLConnection c = new SQLConnection(connectionString))
using(SQLCommand cmd = new SQLCommand(c))
{
c.Open();
string w = "insert into checkmultiuser(username) values (#username)";
cmd.CommandText = w;
cmd.Parameters.Add("#username", SqlDbType.VarChar);
for(int i = 0; i < value.Length; i++)
{
cmd.Parameters["#username"].Value = value[i];
cmd.ExecuteReader();
}
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
If you can create the SQLConnection in the method then it will also allow you create it in a using statement, again taking care of managing and releasing resources.
In terms of the statement you are using I can't see any problems with it, you're using parameterized queries which is a good step to take when interacting with SQL databases.
References:
try-catch - MSDN
I don't think you should have to worry about the time lag due to opening and closing a connection, particularly if it is happening on a manually triggered button click event. Human perceivable response time is about 200 milliseconds. At best, I'd guess someone could click that button once every 100 milliseconds or so. Plenty of time to open and close a connection.
If, however, you are dealing with a routine that will be connecting to your database, you could pass in the connection, include a using statement as Mr. Keeling mentioned already, and just verify that it is ready.
Here is yet another approach, which returns a DataTable (since your original post displayed executing a Data Reader):
public static DataTable UpdateRoutine(SQLConnection c, string value) {
const string w = "insert into checkmultiuser(username) values (#username)";
DataTable table = new DataTable();
using(SQLCommand cmd = new SQLCommand(w, c)) {
cmd.Parameters.Add("#username", SqlDbType.VarChar);
cmd.Parameters["#username"].Value = value;
try {
if ((cmd.Connection.State & ConnectionState.Open) != ConnectionState.Open) {
cmd.Connection.Open();
}
using (SqlDataReader r = cmd.ExecuteReader()) {
table.Load(r);
}
}
return table;
} catch(SqlException err) { // I try to avoid catching a general exception.
MessageBox.Show(err.Message, "SQL Error");
}
return null;
}

C# SQL connection problem

i am using VS.NET 2008 with MS SQL server 2005 to develop a window form application but everytime i got new error in connection or after conected,
in my current code the connection opened but doesnt work after that in transaction of queries. maybe i have problem while making new DB or new datasource also m not that satisfy how to get Connecting String
this is my code....
/////////
private void button1_Click(object sender, EventArgs e)
{
try
{
//setData();
string ConnectingString = #"Data Source=SERVER1\SQLEXPRESS;Initial Catalog=Alkawthar;Integrated Security=True;Pooling=False";
qry = "SELECT * FROM Table1";
//reader = db.select_data(qry);
ds1 = new DataSet();
conn = new SqlConnection(ConnectingString);
conn.Open();
MessageBox.Show("connection opened");
da.Fill(ds1,"Workers");
NavigateRecords();
MaxRows = ds1.Tables["Workers"].Rows.Count;
string sql = "SELECT * From tblWorkers";
da = new System.Data.SqlClient.SqlDataAdapter(sql, conn);
conn.Close();
MessageBox.Show("connection closed");
conn.Dispose();
}
catch (Exception ex)
{
MessageBox.Show("exception");
MessageBox.Show(ex.Message);
}
}
/////////////////
Fill throws an exception also when i use reader it return null although there is data in DB
thanks
The most obvious problem here is that you access the SqlDataAdapter before initializing it. That will cause a null reference exception.
Try to move the line da = new SqlDataAdapter(...) to the line before you do the da.Fill(...).
Edit:
No, wait! I see that you do two queries and two fills in there. You need to initialize the SqlDataAdapter before doing the first fill. Then you should get rid of the null reference exception.
Edit again:
Also, as commented, you don't need call both the SqlConnection.Close and SqlConnection.Dispose methods. As long as you use the SqlDataAdapter you don't even need to do the SqlConnection.Open on the connection, for the Fill method will do all that for you. As long as the connection starts out being closed, the Fill method will close it again for you when it is done.
A few points of advice;
Like Turrau and Rune say, your stuff is in the wrong order. Open connection, Execute SQL - Get raw data, close connection. Then do your counting, etc.
Don't put message box or logging calls anywhere in between the connection opening and closing. This has burned me before, where the those calls can affect the SQL call because they fudge the exception details and make it difficult to trace. This is also applicable when using a SQL data reader.
Put the SQL stuff in a using block.
Try this...
string _connStr = #"Data Source=SERVER1\SQLEXPRESS;Initial Catalog=Alkawthar;Integrated Security=True;Pooling=False";
string _query = "SELECT * FROM Workers";
DataSet _ds = new DataSet();
try
{
using (SqlConnection _conn = new SqlConnection(_connStr))
{
SqlDataAdapter _da = new SqlDataAdapter(_query, _conn);
_conn.Open();
_da.Fill(_ds);
}
// insert null dataset or invalid return logic (too many tables, too few columns/rows, etc here.
if (_ds.Tables.Count == 1)
{ //There is a table, assign the name to it.
_ds.Tables[0].TableName = "tblWorkers";
}
//Then work with your tblWorkers
}
catch (Exception ex)
{
Console.Write("An error occurred: {0}", ex.Message);
}
Seems to me, that you use your DataAdapter before initialization. Do you get a NullReferenceException?
da.Fill(ds1,"Workers");
// ...
da = new System.Data.SqlClient.SqlDataAdapter(sql, conn);

Categories

Resources