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
Related
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/
My data grid view isn't showing the data. I want it to show whole table at runtime and a search option to search specific rows.
SqlConnection con = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\DELL\source\repos\phoneBookwin\phoneBookwin\Database1.mdf;Integrated Security=True");
con.Open();
using (SqlCommand com = new SqlCommand("select * from Contacts"))
{
using (SqlDataAdapter db = new SqlDataAdapter("select * from Contacts", con))
{
DataTable View = new DataTable();
db.Fill(View);
}
}
and this is for searching specific contact
private void search_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\DELL\source\repos\phoneBookwin\phoneBookwin\Database1.mdf;Integrated Security=True");
con.Open();
SqlDataAdapter cmd = new SqlDataAdapter("Select * from Contacts where Name = '"+searchBox.Text+"'",con);
DataTable View = new DataTable();
cmd.Fill(View);
con.Close();
}
The data gridview isn't showing anything whether I click the search button or not.
Your code never assigns the resulting DataTable you filled, to a datagridview; it just fills it then throws it away. You need a call to someDataGridView.DataSource = View after the call to Fill
If, after you do this the datagridview is still blank, it is likely no data was downloaded to the datatable. Check you're connected to the correct database and that the table has data. If you don't see the columns you expect, check that the datagridview's AutoGenerateColumns setting is true
Other points, please ..
..stop writing SQL in the way you currently are, concatenating the value in from a textbox - not only will it fall sort of someone searches for the name O'Connor it also puts you at risk of the most common form of hacking applicable to database software. Read http://Bobby-tables.com - your code should look more like:
using(var da = new SqlAdapter("SELECT * FROM t WHERE c LIKE #p") {
da.SelectCommand.Parameters.Add("#p", SqlDbType.VarChar, 4000).Value = textbox.Text;
//fill etc
}
..make yourself familiar with C# naming conventions. View should be called view because it is a local member, not a publicly accessible class level property
There are a number of issues with your example the primary issue is what you are not yet assigning the table as a source to a Grid as mentioned by Calus Jard.
Additionally, your query with user input being concatenated into a SQL query is very dangerous, I would recommend using a parameter
I am not understanding why I am getting an error after reading documentation in regards to the .Fill(). Am I missing something that is causing this to return with an error?
protected void FillData()
{
using (SqlConnection connection = new SqlConnection(#"Data Source = (LocalDB)\MSSQLLocalDB;AttachDbFilename= C:\Users\home\Documents\C# Programs\shop\Database.mdf ;Integrated Security = True"))
{
connection.Open();
using (SqlDataAdapter dataAdapter = new SqlDataAdapter("select * from Employee", connection))
{
DataTable table = new DataTable();
table.Fill(table);
employeeDataGridView.DataSource = table;
}
}
}
The problem is in this line of code
table.Fill(table);
You can't use table, to fill your table. The correct syntax would be
dataAdapter.Fill(table)
You can't populate a DataTable in that way, you need to fill your DataAdapter, use a DataSet and then set the DataGridView to use this.
using (SqlDataAdapter dataAdapter = new SqlDataAdapter("select * from Employee", connection))
{
var ds = new DataSet();
dataAdapter.Fill(ds);
employeeDataGridView.DataSource = ds.Tables[0];
}
The neatest way to code this up is:
protected void FillData()
{
using (SqlDataAdapter dataAdapter = new SqlDataAdapter("select * from Employee", #"Data Source = (LocalDB)\MSSQLLocalDB;AttachDbFilename= C:\Users\home\Documents\C# Programs\shop\Database.mdf ;Integrated Security=True"))
{
DataTable table = new DataTable();
dataAdapter.Fill(table);
employeeDataGridView.DataSource = table;
}
}
It'll get neater if you put your connection string in a static "global" variable somewhere
Points of note:
use the dataadapter constructor that takes two strings - it will create the connection and the command for you
you don't need to open the connection for the adapter- it knows how to
this means you can have just one using
if your sql needs parameters put them inside the using as dataAdapter.SelectCommand.Paramaters.Add...
you could turn this into a method that accepts any sql string and parameter collection and returns you a datatable
consider putting a WHERE clause in your sql; users might not like to see a grid with 20,000 employees in because it makes it harder to edit a handful of employees
It would be better to add a DataSet to your project (right click project, add>>new item, choose dataset - it gives you something that looks like a db visual design surface you can add queries to, create datatables that become components that can be added to your forms/create databound controls automatically) and create strongly typed datatables and table adapters
An alternative better route than this would be to use Dapper and strongly typed POCOs
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.
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.