I have a stored procedure called "WEB_SEL_SECURITY_QUESTIONS" in my sql database which returns a table as follows.
SEQURITY_QUESTIONS_KEY, KEYCODE, QUESTION
I need to populate a html selectbox with the list of questions I get from executing the above procedure.
This is what I have tried
String s = ConfigurationManager.ConnectionStrings["ConnectionString2"].ToString();
SqlConnection con = new SqlConnection(s);
con.Open();
SqlDataAdapter myAdepter = new SqlDataAdapter("WEB_SEL_SECURITY_QUESTIONS", con);
myAdepter.SelectCommand.CommandType = CommandType.StoredProcedure;
DataSet ds = new DataSet();
myAdepter.Fill(ds, "WEB_SEL_SECURITY_QUESTIONS");
String questions = ds.Tables["WEB_SEL_SECURITY_QUESTIONS"].Rows[]["QUESTION"].ToString();
securityQuestion1.DataSource = questions;
securityQuestion1.DataBind();
But this populates the select box with only one record and it generates the list items in such a way that, only one character per list item and only the first record.
You could try:
securityQuestion1.DataSource = ds.Tables["WEB_SEL_SECURITY_QUESTIONS"];
securityQuestion1.DataTextField = "QUESTION";
securityQuestion1.DataValueField = "KEYCODE"; // Or whatever the value field needs to be.
securityQuestion1.DataBind();
What your first attempt was doing is just taking that single value from one question and using that as the entire data source. So what you need to aim for is make the whole security questions table the data source, and then give it hints as to what columns to use for value and display (DataTextField, DataValueField).
Related
I'm trying to save my data from datagridview row to my sql database. My problem is with my current code, it reads and updates all the rows regardless if it has any changes or not. I know this is going to be a problem especially if my table has large amounts of data.
These are what I did with my code so far:
//retrieve data from dbase
public void loadToDGV()
{
DBConn.DBConnect();
SqlDataAdapter sqlDA = new SqlDataAdapter("SELECT * from TableName", DBConnection.conn);
sqlDA.Fill(dataTable);
gridView.DataSource = dataTable;
}
Below is what's in my Save button.
foreach (DataGridViewRow row in gridView.Rows)
{
DBConn.DBConnect();
SqlCommand comm = new SqlCommand();
comm.Connection = DBConnection.conn;
comm = new SqlCommand("SPName", DBConnection.conn);
comm.CommandType = CommandType.StoredProcedure;
comm.Parameters.AddWithValue("#ID", row.Cells["ID"].Value == DBNull.Value ? "" : row.Cells["ID"].Value);
comm.ExecuteNonQuery();
}
I have another sample code where I can only save modified rows
changeTable = dataTable.GetChanges(DataRowState.Modified);
foreach (DataRow row in changeTable.Rows)
{
DBConn.DBConnect();
SqlCommand comm = new SqlCommand();
comm.Connection = DBConnection.conn;
comm = new SqlCommand("SPName", DBConnection.conn);
comm.CommandType = CommandType.StoredProcedure;
comm.Parameters.AddWithValue("#ID", row["ID"].ToString());
comm.ExecuteNonQuery();
}
What I wanted to do is save only BOTH the "New Rows" AND "Modified Rows".
Is there any way to only get newly added/edited rows? and not include all the rows from the gridview?
My Stored Procedure only checks if the ID is existing or not.
IF NOT EXISTS (SELECT 1 FROM TABLE WHERE ID = #ID)
-- INSERT QUERY
ELSE
-- UPDATE QUERY
You should not be using a loop at all, nor even referring to the grid. You obviously have a DataTable already. If you're not already doing so, populate it with a data adapter, bind it to a BindingSource and bind that to the grid. When it's time to save, call EndEdit on the BindingSource call Update on the data adapter and pass the DataTable. That's it, that's all. There's no need to call GetChanges.
Obviously you will have to configure the data adapter appropriately, with an InsertCommand to insert new records and an UpdateCommand to save modified records. I won't go into specifics as you haven't gone into specifics but there are plenty of examples around. You can find my own here.
EDIT:
The short answer to your question is that, if you want both modified and added rows, then specify both Modified and Added rows. The DataRowState enumeration has the Flags attribute, which means that you can create compound values. That would mean that this:
changeTable = dataTable.GetChanges(DataRowState.Modified);
would become this:
changeTable = dataTable.GetChanges(DataRowState.ModifiedData Or RowState.Added);
If you were going to then loop through those rows, you wouldn't create a new command object every iteration. You'd create one command and add the parameters once, then simply set the Value of each parameter in the loop. You would also need to call AcceptChanges on the original DataTable afterwards.
You should do any of that though. As I said, you should use the same data adapter as you used to retrieve the data to save the changes. Normally you'd use different SQL for the InsertCommand and UpdateCommand but, in your case, you can use the same. Just create a single command object with the appropriate parameters and assign it to both the InsertCommand and UpdateCommand properties, then call Update.
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 have this code where I put data to the DataTable from where I show everything on DataGridView.
But when I look it contains information which supposed to be in file but its repeated twice.
Code to retrieve data from mysql database:
MySqlDataAdapter mySqlDataAdapter;
DataSet DS0 = new DataSet();
DataTable DT0;
string gender;
private void Filter()
{
ViewG.DataSource = null;
ViewG.Rows.Clear();
command.CommandText = "SELECT * FROM `table2` WHERE s1q2 = #gender";
command.Parameters.Add("#gender", MySqlDbType.VarChar);
command.Parameters["#gender"].Value = gender;
DT0 = DS0.Tables.Add("1Filter");
mySqlDataAdapter = new MySqlDataAdapter(command.CommandText, connection);
connection.Open();
mySqlDataAdapter.SelectCommand = command;
mySqlDataAdapter.Fill(DS0.Tables["1Filter"]);
ViewG.DataSource = DS0.Tables["1Filter"];
connection.Close();
}
Initially, on the start it retrieves all information from the database code (SELECT * FROM table) and displays on the DataGridView. And it works fine, but when I try to use filters to retrieve only for example "Females" problem occurs.
For full data I use:
mySqlDataAdapter.Fill(DS0.Tables["Full"]);
ViewG.DataSource = DS0.Tables["Full"];
For Filtered data:
mySqlDataAdapter.Fill(DS0.Tables["1Filter"]);
ViewG.DataSource = DS0.Tables["1Filter"];
If I run query used for filter on the application startup it does not duplicate and show correctly.
EDIT: SOLVED
From the code posted here, gender string is not assigned any value. So, your query be applying any filter that you want.
Thanks for you effort I found where the problem was. I used temp table on MySql and for some reason server did not dropped this table after connection is closed. So on the new query it added same items on the same table....
Note: my office doesn't allow me to view YouTube and several other sites that probably have the answer to this question on them (they are blocked), which is why Googling the answer hasn't yielded results.
ComboBox code reference: found here
On my C# Form, I have filled a ComboBox with tables from a database (see below code), which returns the appropriate values and functions correctly:
public Form1()
{
InitializeComponent();
// Connection
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "CONNECTION STRING" // shortened for security and convenience
// Fill ComboBox with SQL Values
conn.Open();
SqlCommand cmbTables = new SqlCommand("SELECT name FROM sys.tables", conn);
SqlDataReader read = cmbTables.ExecuteReader();
DataTable cmbData = new DataTable();
cmbData.Columns.Add("name", typeof(string));
cmbData.Load(read);
cmb1.DisplayMember = "name";
cmb1.DataSource = cmbData;
conn.Close();
}
After the ComboBox loads the tables (which works), the application then selects a table and clicks a button that loads the table, which is selected. This is where the code errors:
private void button1_Click(object sender, EventArgs e)
{
using (var connection = Utilities.GetConnection())
{
string table = Convert.ToString(txt1.Text);
string cmb1Value = Convert.ToString(cmb1.SelectedItem);
// Stored Procedure
SqlCommand select = new SqlCommand("EXECUTE STOREDPROCEDURE" + cmb1Value, connection); // shortened for security and convenience
select.Parameters.Add(new SqlParameter(cmb1Value, table));
// Data View
SqlDataAdapter ad= new SqlDataAdapter(select);
ad.SelectCommand = select;
DataTable dt = new DataTable();
ad.Fill(dt); // this generates the error "Incorrect Syntax Near '.'"
BindingSource b = new BindingSource();
b.DataSource = dt;
dGrid.DataSource = b;
ad.Update(dt);
connection.Close();
}
}
Even though the ComboBox loads the appropriate values, from the above code, I may be missing something which attaches those values to the SELECT stored procedure (all it does is call SELECT statement through a variable passed to it). The error, "Incorrect Syntax Near '.'" looks like a SQL Server error that I've seen, but can't remember how I generate it (this is how I usually troubeshoot where the TSQL code went wrong).\
Stored Procedure Related code:
C#:
SqlCommand select = new SqlCommand("EXECUTE STOREDPROCEDURE " + cmb1Value, connection);
TSQL:
CREATE PROCEDURE [STOREDPROCEDURE]
#TableName VARCHAR(250)
AS
BEGIN
DECLARE #sql NVARCHAR(MAX)
SET #sql = N'SELECT TOP 100 *
FROM ' + #TableName
EXECUTE(#sql)
END
-- Note this works in SSMS without a problem.
The above code is incorrect, and when I tweak the TSQL code, I generate similar errors, telling me that somewhere I am missing a conversion, or another variable because SQL Server isn't seeing these table values returned by the SELECT (first block of code). I can ascertain this because I have a second ComboBox that uses similar code EXCEPT that I populated the ComboBox with manual values, and it connects to the tables in the database with no error. So, the ComboBox, which grabs values from the database, that you see above, does not function correctly.
For instance, if I only add the below line of code to the code, I receive an error that it can't find the database "EXECUTE STOREDPROCEDURE System'
select.CommandType = CommandType.StoredProcedure;
However, System isn't a part of anything, so where did that come from? It never errored with this code on the manual ComboBox, as it had no trouble finding the database (using the same connection string, server and database!).
If I try to use a TSQL parameter, such as:
SqlCommand select = new SqlCommand("EXECUTE stp_ReturnTable #p", scon);
select.Parameters.Add(new SqlParameter("#p", cmb1Value));
Suddenly, it can't find the stored procedure. Again, the connection strings are identical for the manual ComboBox and the dynamic ComboBox.
I think the code behind the dynamic ComboBox is wrong. When I'm out of the office, I'll review some videos with detailed demonstrations on how to create a dynamic ComboBox from a database and I have a hunch that a system object is in the way (based on the System error, which exists nowhere in my code, as well as it suddenly being unable to find the database or procedure).
The missing key point in your code is the CommandType.
Without the proper set of this property the default is CommandText and thus the Framework expects a statement that starts with SELECT/INSERT/UPDATE/DELETE etc....
using (var connection = Utilities.GetConnection())
{
string table = Convert.ToString(txt1.Text);
string cmb1Value = Convert.ToString(cmb1.SelectedItem);
// Stored Procedure
SqlCommand select = new SqlCommand("STOREDPROCEDURE", connection);
select.Parameters.Add(new SqlParameter("#TableName", cmb1Value));
// That's the key to let ADO.NET accept the previous CommandText as valid.
// If you omit this the CommandText is assumed to be a SELECT/UPDATE/DELETE etc..
select.CommandType = CommandType.StoredProcedure;
// Data View
SqlDataAdapter ad= new SqlDataAdapter(select);
DataTable dt = new DataTable();
ad.Fill(dt);
BindingSource b = new BindingSource();
b.DataSource = dt;
dGrid.DataSource = b;
}
EDIT Having seen the code of the SP then you could simply set the SqlParameter name to the constant #TableName and pass the value extracted from the combobox as the value to be used inside the SP
EDIT I have looked again at your code and I suspect that the culprit is the line
string cmb1Value = Convert.ToString(cmb1.SelectedItem);
Looking at how you have filled your combo, this line, doesn't return the tablename as you expect, but the generic string System.Data.DataRowView because the DataSource of the combo is a DataTable and not a string collection. You should try to change that line in this way
DataRowView rw = cmb1.SelectedItem as DataRowView;
if(rw != null)
{
string cmbValue1 = rw["name"].ToString();
....
And yes, your code should work also without the CommandType.StoredProcedure line because the text EXECUTE sp param is recognized as a valid sql commandtext (but why do you use it when a direct call to the storedprocedure could be optimized for reuse?)
I am trying to populate some text boxes on a form with data pulled from MySQL into a data set.
I cant seem to get the code right and could use some help
string ConnectionString = ConfigurationSettings.AppSettings["ConnectionString"];
MySqlConnection connection;
MySqlDataAdapter adapter;
DataTable DTItems;
connection = new MySqlConnection(ConnectionString);
try
{
//prepare query to get all records from items table
string query = "select * from spt_proposal where fr_Numer = "+ a+"";
//prepare adapter to run query
adapter = new MySqlDataAdapter(query, connection);
DataSet DS = new DataSet();
//get query results in dataset
adapter.Fill(DS);
textBox5.Text = DS.Tables[0].Rows[0].ToString();
This does not hit the text box at all.
a in the query is a variable that is pulled from a different form
and the query should pull 32 different things from the database in a row
There are about 9 text boxes on the form that i will have to fill with different data from this row.
Anyone have a better way to do this?
Brent
Try:
textBox5.Text = DS.Tables[0].Rows[0][0].ToString();
Remember, that a Table is pretty much a two dimensional array. Your code literally gets to the 1st row in the DataSet, but doesn't take into account the Column.