Writing to SQL Server Database - c#

I am having trouble writing my datagrid changes to the database, i am trying to type in the changes on the grid and then when Button_Add_Car is pressed i execute this code and write changes to the database but nothing is being written to the database.
private void Button_Add_Car(object sender, RoutedEventArgs e)
{
SqlConnection cn = new SqlConnection();
DataSet dt = new DataSet();
SqlDataAdapter da;
SqlCommandBuilder cmdBuilder;
cn.ConnectionString = (String.Format("Data Source={0};Initial Catalog={1};Persist Security Info=True;User ID={2};Password={3}", SQLFunctions.connectSQL.SQLSERVER_ID, SQLFunctions.connectSQL.SQLDatabaseName, SQLFunctions.connectSQL.SQLServerLoginName, SQLFunctions.connectSQL.SQLServerPassword));
cn.Open();
da = new SqlDataAdapter("SELECT * FROM Cars", cn);
cmdBuilder = new SqlCommandBuilder(da);
da.Fill(dt);
da.Update(dt);
cn.Close();
}
Am i on the right track using this method?
Am i using the correct SQL Query? I am confused between the SELECT/INSERT as i have found examples where people are using both to achieve what i want to do. Surely i should be using the INSERT statement.
I made my own custom SQL Command to manually insert into the database so it is in fact working:
SQLCmd("INSERT INTO Cars (Date, Time) VALUES(2014-10-10, '12:00:00')");
EDIT 1:
Thanks to marc_s i managed to achieve some sort of inserting but i believe i need to modify the value section to be inside an IF Statement which will check if it is a null or not and change value back to cr.Date and cr.Time as i am making use of a list. I am unsure of how to utilize the if statement in this way because it is currently entering blank rows, although its a step in the right direction:
CarRecord cr = new CarRecord();
carRecords.Add(cr);
SqlConnection con = new SqlConnection(String.Format(#"Data Source={0};Initial Catalog={1};Persist Security Info=True;User ID={2};Password={3}", SQLFunctions.connectSQL.SQLSERVER_ID, SQLFunctions.connectSQL.SQLDatabaseName, SQLFunctions.connectSQL.SQLServerLoginName, SQLFunctions.connectSQL.SQLServerPassword));
con.Open();
SqlCommand comm = new SqlCommand("INSERT INTO Cars VALUES (#Date, #Time)", con);
SqlDataAdapter da = new SqlDataAdapter(comm);
da.SelectCommand.Parameters.Add(new SqlParameter("#Date", SqlDbType.NVarChar)).Value = DBNull.Value;
da.SelectCommand.Parameters.Add(new SqlParameter("#Time", SqlDbType.NVarChar)).Value = DBNull.Value;
da.SelectCommand.ExecuteNonQuery();
DataTable dt = new DataTable();
SqlCommandBuilder builder = new SqlCommandBuilder(da);
da.Update(dt);
con.Close();

lets take your first code example.
take a look at the last 3 lines, first thing you do is to copy data from the table Cars and store that into the DataSet named dt.
then immediately after you store this dataset back into the database, without actually doing any changes.
if dot net is smart enough it wont do anything, since you didn't change anything between the fill and the update call.
what you probably should be doing is get the dataset from the datagrid or similar and store that one instead.
or do as you have started on in your second example of when you identity that a row is updated take the data from that row and construct an insert (or update) query to the database.

Related

WPF insert to database executes but no data added

I have a small table (tbl_user_favs) that is meant to store user favorites. Column 1 is the user ID, and then every column after that is a slot for a selected favorite PC to be stored, denoted Slot1, Slot2.
using (SqlConnection con = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\UserFavorites.mdf;Initial Catalog=tbl_user_favs;Integrated Security=True;Connect Timeout=30"))
{
string cmdString = ("SELECT * FROM tbl_user_favs WHERE UserID = '" + Globals.emailUID + "'");
SqlCommand cmd = new SqlCommand(cmdString, con);
cmd.Parameters.Add("#Slot1", SqlDbType.VarChar).Value = PCnum;
DataSet loginCredentials = new DataSet();
SqlDataAdapter dataAdapter;
con.Open();
//dataAdapter = new SqlDataAdapter(cmdString, con);
dataAdapter = new SqlDataAdapter(cmd);
dataAdapter.Fill(loginCredentials);
//cmd.ExecuteNonQuery();
con.Close();
}
Code executes, but it does not add the PCnum to the database next to the UserID. It should lok through the rows, find the UserID that matches the logged in user, Globals.emailUId, and add the PCnum to an open slot. Without worrying yet how to dynamically increment the Slots, why isn't this insert adding the PCnum to Slot 1? I've seen some tutorials use ExecuteNonQuery, and some use the dataAdapter, but both have the same result. I suspect there is something off with my SQL? Thank you
There are a couple things going on here.
First is that you are using "Parameters" incorrectly. It's supposed to add data to your query, not data to the database/row/column after a query has been made.
sql parameterized query in C# with string
Second, you are doing a select query, so you are only getting data from the db, not putting data into it.
To do what you want, you'd need to do this instead: (I don't have a good way to test this, so it may need tweaks, but it should be close.)
using (SqlConnection con = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\UserFavorites.mdf;Initial Catalog=tbl_user_favs;Integrated Security=True;Connect Timeout=30"))
{
string cmdString = ("UPDATE tbl_user_favs SET Slot1 = #Slot1 WHERE UserID = #EmailUID");
SqlCommand cmd = new SqlCommand(cmdString, con);
cmd.Parameters.AddWithValue("#Slot1", PCnum);
cmd.Parameters.AddWithValue("#EmailUID", Globals.emailUID);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
You no longer need the DataSet or the SqlDataAdapter.
Since you seem to be confused on what parameterization is and why to use it, check out this question, too.
And here's just some more reading on the topic in general. I used these articles as resources for this answer:
https://visualstudiomagazine.com/articles/2017/07/01/parameterized-queries.aspx
https://www.c-sharpcorner.com/UploadFile/a20beb/why-should-always-use-the-parameterized-query-to-avoid-sql-i/

c# How to clear oledbconnection cache, multiple excel queries erroring out

Sorry for the vague title but I'm not sure how best to word it.
Basically, the issue that I'm having is that I initially was using an oledbconnection in C# to initiate a connection to a spreadsheet, query it, and load the results into a .net datatable. Unfortunately, it maxes out at 255 fields which I have around 600.
So, what I did instead was I created a dataset and tried to load 4 separate data tables with separate queries. Now for some reason, what's crazy to me is, if I load lets say, the first data table with 190 fields, and then I go on to query the spreadsheet again, if I go over that 250 mark (which I'd have 60 left), I get the following error:
An exception of type 'System.Data.OleDb.OleDbException' occurred in System.Data.dll but was not handled in user code
Additional information: No value given for one or more required parameters.
If I reduce the amount of fields in the second table to equal less than 250 though, it works. Anyway, is there a way that I can somehow clear the cache of the oledbconnection to somehow drop the first 190 fields or whatever is holding the result of the excel query so I can move on to the next? I tried doing a data adapter dispose but that didn't work, same issue. If I do a connection.dispose, I have to re-initialize the connection anyway. Is there a way I can still do this without having to drop the connection? Code below:
OleDbConnection cnn = new OleDbConnection(Settings.ExcelCN);
OleDbCommand fillT1 = new OleDbCommand(Settings.Excel_Proj_Select_1, cnn);
OleDbCommand fillT2 = new OleDbCommand(Settings.Excel_Proj_Select_2, cnn);
OleDbCommand fillT3 = new OleDbCommand(Settings.Excel_Proj_Select_3, cnn);
OleDbCommand fillT4 = new OleDbCommand(Settings.Excel_Proj_Select_4, cnn);
OleDbCommand updateCnt = new OleDbCommand(Settings.Excel_Update_Count_Select, cnn);
cnn.Open();
OleDbDataAdapter adp1 = new OleDbDataAdapter(fillT1);
OleDbDataAdapter adp2 = new OleDbDataAdapter(fillT2);
OleDbDataAdapter adp3 = new OleDbDataAdapter(fillT3);
OleDbDataAdapter adp4 = new OleDbDataAdapter(fillT4);
DataTable dt1 = new DataTable();
DataTable dt2 = new DataTable();
DataTable dt3 = new DataTable();
DataTable dt4 = new DataTable();
DataSet ds1 = new DataSet();
adp1.Fill(dt1);
ds1.Tables.Add(dt1);
adp2.Fill(dt2);
ds1.Tables.Add(dt2);
adp3.Fill(dt3);
ds1.Tables.Add(dt3);
adp4.Fill(dt4);
ds1.Tables.Add(dt4);
int rowcount = updateCnt.ExecuteNonQuery();
cnn.Close();

SELECT Statement Using CheckedListBox Values

I need to populate a second CheckedListBox with the results of a query whose values are dependent upon which options are checked in the initial CheckedListBox, re-Querying every time another box is checked or unchecked.
Additionally helpful would be a way to re-use the SqlConnection I'm utilizing. It seems to be a simple thing, but I can't figure out how to do it. Right now I've got this.
private void Connection()
{
SqlConnection conn = new SqlConnection("Data Source=(local);Initial Catalog=Project;Integrated Security=True");
conn.Open();
DataSet ds = new DataSet();
SqlDataAdapter adapter = new SqlDataAdapter
("SELECT [StandardCode], c.CanStatement, [StandardDetail] FROM [dbo].[StandardCodesAndDetails] s JOIN dbo.CanStatements c ON c.StandardsID=s.ID", conn);
adapter.Fill(ds);
this.lstBoxStandardCodes.DataSource = ds.Tables[0];
this.lstBoxStandardCodes.DisplayMember = "StandardCode";
//conn.Close();
}
On Initialization, it populates the first CheckedListBox (lstBoxStandardCodes), and I'm looking for a way to adjust those last two lines to accept variable input, to use it toward my first issue, if that makes sense. lstBoxStandardCodes would be changed to lstBoxStandardDetails (in this case), and "StandardCode" would become "StandardDetails". That last bit seems easy enough by changing private void Connection() to private void Connection(string Member) or such, but the rest isn't quite clicking for me.
If any further clarification is needed, please let me know. Thank you.
Here you go, I tested this locally, and it works fine.
private void Connection()
{
//Please use a using statement as below
using (SqlConnection conn = new SqlConnection("Data Source=PWALTON-ACER;Initial Catalog=pwalton-test;Integrated Security=True"))
{
conn.Open();
DataSet ds = new DataSet();
SqlDataAdapter adapter = new SqlDataAdapter
("SELECT [StandardCode], c.CanStatement, [StandardDetail] FROM [dbo].[StandardCodesAndDetails] s JOIN dbo.CanStatements c ON c.StandardsID=s.ID", conn);
adapter.Fill(ds);
lstBoxStandardCodes.DataSource = ds.Tables[0];
lstBoxStandardCodes.DataTextField = "StandardCode";
lstBoxStandardCodes.DataBind(); //Don't forget to DataBind()
lstBoxStandardDetails.DataSource = ds.Tables[0];
lstBoxStandardDetails.DataTextField = "StandardDetail";
lstBoxStandardDetails.DataBind(); //This list won't populate if you don't DataBind()
}
}
There wasn't any info included about the backing tables, but I deduced that it was probably something like this (based on the inline SQL in the original post): SQL Fiddle

Update DataGrid after insert with procedure

I know this question was asked but I can't figure out why this action is so complex.
So I have a Produs table
SELECT TOP 1000 [IDProdus]
,[Denumire]
,[UM]
,[Pret]
,[IDFurnizor]
,[IDCategorie]
,[IDTipProdus]
,[OperatorAdaugare]
,[DataAdaugare]
,[OperatorModificare]
,[DataModificare]
FROM [Proiect].[dbo].[Produse]
This is my table's columns. I added via Data Sources GUI from Visual Studio a DataSet with the content of this table (no actual code wrote by me).
Now I have a procedure that will insert me a new row in this Table.
Here is the code:
private void dToolStripMenuItem_Click(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection("connection-string-here");
string Query = "spGE_getProduse_Edit"; // Stored procedure name.
int Integer;
conn.Open();
// Creating SqlCommand object
SqlCommand com = new SqlCommand(Query, conn );
// Here we declaring command type as stored procedure:
com.CommandType = CommandType.StoredProcedure;
com.Parameters.AddWithValue("#IDProdus", 0);
com.Parameters.AddWithValue("#Denumire ",
denumireTextBox.Text.ToString());
com.Parameters.AddWithValue("#UM ",
uMTextBox.Text.ToString());
com.Parameters.AddWithValue("#Pret ",
Double.Parse(pretTextBox.Text));
com.Parameters.AddWithValue("#IDFurnizor ",
Int16.Parse(iDFurnizorTextBox.Text));
com.Parameters.AddWithValue("#IDCategorie ",
Int16.Parse(iDCategorieCombobox.SelectedValue.ToString()));
com.Parameters.AddWithValue("#IDTipProdus ",
Int16.Parse(iDTipProdusCombobox.SelectedValue.ToString()));
com.Parameters.Add("#IDProdusScris", SqlDbType.BigInt);
com.Parameters["#IDProdusScris"].Direction =
ParameterDirection.Output;
com.ExecuteNonQuery();
conn.Close();
Integer =
Int32.Parse(com.Parameters["#IDProdusScris"].Value.ToString());
}
Now after insert I want to update myGrid with the new record. I tried
dataGridView1.Refresh(); and dataGridView1.Update();, with no result.
Is there a way to update the grid? It looks like a simple task for VS, but I couldn't find a simple solution.
What I saw only and read on MSDN looked like some very complex operations just for a simple refresh. (It was about getting the state of the row and insert the row if the state was Added).
So is there any simple way to do this, or I have to write a method that will refresh my dataGridView every time I want (I mean to re-query my table and rebuild the dataSource)
Try like this:
dataGridView1.Refresh(); and dataGridView1.Update(); will not fetch updated records from db.
Source
You can use stored procedures are pre-complied
Create Procedure Sp_getProducts
as
BEGIN
SELECT TOP 1000 [IDProdus]
,[Denumire]
,[UM]
,[Pret]
,[IDFurnizor]
,[IDCategorie]
,[IDTipProdus]
,[OperatorAdaugare]
,[DataAdaugare]
,[OperatorModificare]
,[DataModificare]
FROM [Proiect].[dbo].[Produse]
END
Use this code which Uses Using Statements
using (SqlConnection conn = new SqlConnection("connection-string-here"))
{
conn.Open();
using(SqlCommand cmd=new SqlCommand("Sp_getProducts",conn))
{
cmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable ds = new DataTable();
da.Fill(ds);
gridView.DataSource = ds;
gridView.DataBind();
conn.Close();
}
}
Try resetting your datasource:
dataGridView1.DataSourcce = null;
dataGridView1.DataSource = [YOUR DATASET];
dataGridView1.Refresh();
dataGridView1.Update();

object reference not set to an instance of an object when using parameter

Can someone tell me how i can set the object reference to an instance? ....
Here, user_id is the parameter which takes a textbox value into the sql statement.
private void button1_Click(object sender, EventArgs e)
{
OracleConnection con = new OracleConnection("Data Source=KBETEST; Persist Security Info=TRUE; User ID=dbo; Password=dbo123; Unicode=True");
DataSet ds = new DataSet();
OracleDataAdapter adap = new OracleDataAdapter();
OracleCommandBuilder b = new OracleCommandBuilder(adap);
adap = new OracleDataAdapter("insert into banks_ben_branch_99 (ben_bank_id, ben_brn_code, brn_name,ben_brn_addr1, ben_brn_loc, ben_brn_state, ben_brn_city, ben_bank_city, coun_code,brn_stat, remarks, brn_id, user_id, pc_tcp_ip, rtgs_stat, pay_brn_code,sys_date) select bankid,benbrn_code,brn_name,substr(brn_addr,1,100),brn_loc, brn_stat, brn_city, brn_city, coun_code,'A', remarks, '15', :user_id,'172.20.1.109', rtgs_stat, benbrn_code,sysdate from bbbt",con);
adap.InsertCommand.Parameters.Add("user_id", OracleType.VarChar,20, "user_id").Value = textBox1.Text;
adap.Fill(ds,"A");
DataTable table = ds.Tables["A"];
dataGridView1.DataSource = ds.Tables["A"];
con.Dispose();
}
thanks!
edit
private void button1_Click(object sender, EventArgs e)
{
OracleConnection con = new OracleConnection("Data Source=KBETEST; Persist Security Info=TRUE; User ID=dbo; Password=dbo123; Unicode=True");
DataSet ds = new DataSet();
OracleDataAdapter adap = new OracleDataAdapter();
OracleCommandBuilder b = new OracleCommandBuilder(adap);
string str = "insert into banks_ben_branch_99 (ben_bank_id, ben_brn_code, brn_name,ben_brn_addr1, ben_brn_loc, ben_brn_state, ben_brn_city, ben_bank_city, coun_code,brn_stat, remarks, brn_id, user_id, pc_tcp_ip, rtgs_stat, pay_brn_code,sys_date) select bankid,benbrn_code,brn_name,substr(brn_addr,1,100),brn_loc, brn_stat, brn_city, brn_city, coun_code,'A', remarks, '15', :user_id, '172.20.1.109', rtgs_stat, benbrn_code,sysdate from bbbt";
con.Open();
adap.InsertCommand = new OracleCommand(str, con);
adap.InsertCommand.Parameters.Add("user_id", OracleType.VarChar,20).Value = textBox1.Text;
adap.InsertCommand.ExecuteNonQuery();
con.Dispose();
}
thanks everyone for your help!! i got it!
EDIT: There are multiple things wrong with your code:
You're not specifying the user_id parameter in the command, although it's in the SQL
You're trying to use the InsertCommand of the adapter even though you haven't specified any insertion SQL
You're trying to fill a dataset, but you haven't specified a query - just an insert command.
I suspect you shouldn't be using a data adapter at all. If you just need to insert some data, use:
using (var connection = new OracleConnection(...)
{
connection.Open();
string sql = "insert into banks_ben_branch_99 [... as before ...]";
using (var command = new OracleCommand(sql, conn))
{
command.Parameters.Add("user_id", OracleType.VarChar, 20)
.Value = textBox1.Text;
command.ExecuteNonQuery();
}
}
I suspect adap.InsertCommand is null in the following line:
adap.InsertCommand.Parameters.Add
On the previous line you use the following constructor:
adap = new OracleDataAdapter("insert into ...", con);
but this constructor initializes the SelectCommand, not the InsertCommand. Therefore adap.InsertCommand will still have its default value, null.
Your code then goes on to attempt to fill a DataTable using this adapter:
adap.Fill(ds,"A");
but this won't work either: you need a SelectCommand to do this.
To fill a DataSet, your code should probably look something like:
adap = new OracleDataAdapter("SELECT ... FROM ... WHERE ...", con);
adap.SelectCommand.Parameters.Add(... any parameters you need ...);
adap.Fill(ds, "A");
it is passing the break point now, no changes has been made to the oracle database tables! why is this happening.
I think you're misunderstanding how DataAdapters work.
To get data from the database into your DataTable, you need to:
Create an adapter with a SelectCommand
Call adapter.Fill to execute the SelectCommand and fill the DataTable with the result
To insert data into the database from your DataTable, you need to:
Insert a row into your DataTable with the data you want to insert
Create an adapter with an InsertCommand
Call adapter.Update to insert the data into the database.
Updating / Deleting rows in the database is similar to inserting, but uses UpdateCommand and DeleteCommand.
I think user_id is not a nullable column and it occurs when your parameter is empty. First thing is, parameter name does not match. After that, it still can happen when textbox is empty. It is better to check on client side for validation.
The parameter that you have given is null.

Categories

Resources