In my code behind of aspx page I have problem to passed values on Parameters in sql query.
I use MySql database.
Step 1:
I add in List the output of an query:
while (reader.Read())
{
idcolor = reader["idcolor"].ToString();
colorList.Add(idcolor.ToString());
}
ns = string.Join("','", colorList.ToArray());
In debug the output is:
ns = red','green
Step 2:
I need use the values of string ns on a sql query.
And pass the values of string ns in parameters:
str = null;
str = ns == null ? "" : ns.ToString();
sql = #" SELECT * FROM Experience WHERE Colors IN (?); ";
DataSet dsColors = new DataSet();
using (OdbcConnection cn =
new OdbcConnection(ConfigurationManager.ConnectionStrings["ConnMySQL"].ConnectionString))
{
cn.Open();
using (OdbcCommand cmd = new OdbcCommand(sql, cn))
{
cmd.Parameters.AddWithValue("param1", Server.UrlDecode(str.ToString()));
OdbcDataAdapter adapter = new OdbcDataAdapter(cmd);
adapter.Fill(dsColors);
}
}
return dsColors;
Step 3:
If used in query :
sql = #" SELECT * FROM Experience WHERE Colors IN (?); ";
The output in dataset is empty.
If used in query :
sql = #" SELECT * FROM Experience WHERE Colors IN ( '" + Server.UrlDecode(str.ToString()) + "' ); ";
The output in dataset is right.
Anybody know how can I resolve do this?
Can you suggest?
Can you help me?
Thank you in advance.
you have to use MySql.Data.MySqlClient; to connect to Mysql:
sql = #" SELECT * FROM Experience WHERE Colors IN (#param1,#param2) ";
DataSet dsColors = new DataSet();
using ( MySqlConnection cn =
new MySqlConnection(ConfigurationManager.ConnectionStrings["ConnMySQL"].ConnectionString))
{
cn.Open();
using (MySqlCommand cmd = new MySqlCommand(sql, cn))
{
cmd.Parameters.Add("#param1", colorList[0]/ToString());
cmd.Parameters.Add("#param2",colorList[1].ToString());
MySqlDataAdapter adapter = new MySqlaAdapter(cmd);
adapter.Fill(dsColors);
}
}
if you dont want to add a parameter for each color, you can go with
MySql.Data.MySqlClient.MySqlHelper.EscapeString()
that's not pretty but it's internal used by parameters and you can add a dynamic number of values and you're safe against injection
while (reader.Read())
{
idcolor = reader["idcolor"].ToString();
colorList.Add(MySql.Data.MySqlClient.MySqlHelper.EscapeString(idcolor));
}
ns = string.Join("','", colorList.ToArray());
You need to add a parameter and place holder for each item you want in your in clause. For example
sql = #" SELECT * FROM Experience WHERE Colors IN (?,?,?); ";
Then add the params for each one.
cmd.Parameters.AddWithValue("param1", Server.UrlDecode(str.ToString()));
Example
List<string> colours = new List<string>();
colours.Add("black");
colours.Add("red");
var placeHolders = string.Join(",",(from colour in colours select "?").ToList());
var sql = #String.Format(" SELECT * FROM Experience WHERE Colors IN ({0}); ",placeHolders);
DataSet dsColors = new DataSet();
using (OdbcConnection cn = new OdbcConnection(ConnectionString))
{
cn.Open();
using (OdbcCommand cmd = new OdbcCommand(sql, cn))
{
foreach(var colour in colours)
{
cmd.Parameters.AddWithValue(colour, colour);
}
OdbcDataAdapter adapter = new OdbcDataAdapter(cmd);
adapter.Fill(dsColors);
}
}
You appear close with the context, but try getting the results for one color at a time and just keep changing the VALUE of the parameter. By calling the FILL, it will just keep adding records to the table each time it is called. However, set your FILL to point to a DataTable instead of a DataSet. So it doesn't keep putting TABLES into your data set, but instead uses the one continues to append to it. This would work if you had 1 color or 1000 colors...
... rest of previous code BEFORE the OdbcCommand
... and ensure clean values for your colors as others have noted.
using (OdbcCommand cmd = new OdbcCommand(sql, cn))
{
// Just to add the parameter "place-holder" for your query
cmd.Parameters.AddWithValue("param1", "");
// DataTable ONCE to receive all the colors being queried
DataTable tblAllColors = new DataTable();
// build the adapter ONCE no matter how many colors you will be querying
OdbcDataAdapter adapter = new OdbcDataAdapter(cmd);
// so for this loop, you are just getting the colors one at a time.
foreach( string s in colorList )
{
// next color you are trying to get... just overwrite the
// single parameter with the new color.
adapter.SelectCommand.Parameters[0].Value = s;
adapter.Fill(tblAllColors);
}
// you would otherwise have to build your query dynamically and keep
// adding parameter-placeholders "?" for each color in a comma list
// as you were attempting... which would be a slightly different query.
}
dsColors.Tables.Add( tblAllColors );
Related
I am coding win form app, which checks on startup right of the currently logged user. I had these right saved in MS SQL server in the table. When importing data to Datatable, there is no problem. But when I want to read value, there is message "cannot find column xy".
SqlDataAdapter sdaRights = new SqlDataAdapter("SELECT * FROM rights WHERE [user]='" + System.Security.Principal.WindowsIdentity.GetCurrent().Name + "'", conn);
DataTable dtRights = new DataTable(); //this is creating a virtual table
sdaRights.Fill(dtRights);
Object cellValue = dt.Rows[0][1];
int value = Convert.ToInt32(cellValue);
MessageBox.Show(value.ToString());
I would like, that program would save the value from SQL to int.
You are assuming that you have rows being returned, would be my first guess. You should loop through your DataTable instead of simply trying to access element 0 in it.
DataTable dtRights = new DataTable();
sdaRights.Fill(dtRights);
foreach(DataRow row in dtRights.Rows) {
Object cellValue = row[1];
int value = Convert.ToInt32(cellValue);
MessageBox.Show(value.ToString());
}
using (SqlConnection con = new SqlConnection("your connection string"))
{
using (SqlCommand cmd = new SqlCommand("SELECT [column_you_want] FROM [rights] WHERE [user] = #user"))
{
cmd.Parameters.AddWithValue("#user", System.Security.Principal.WindowsIdentity.GetCurrent().Name);
con.Open();
int right = Convert.ToInt32(cmd.ExecuteScalar());
}
}
I have following combo boxes bound with data from a sql table.
cmbClassification
cmbAuthor
cmbPublisher
cmbType
I need to extract data based on selected values in these combo boxes.
For example: If I left cmbClassification blank and select values for other 3 combo boxes, my datagridview should show all the data for specific author, specific publisher & specific type regardless of the classification.
I know how to do this for two searching items (using if). but i have 4 items and no idea.
Code for two instances
I think there are 10 search patterns for these 4 combo boxes. how can i handle this? If there are only 2 combo boxes there will be 3 patterns which i will handle as follows:
string con = #"Data Source=ABU_DHABI-1\SQLEXPRESS;Initial Catalog=SLIS;Integrated Security=True";
private void btnView_Click(object sender, EventArgs e)
{
if (cmbAuth.Text == "" && cmbClassi.Text =="")
{
SqlConnection Icon = new SqlConnection(con);
String Query = "SELECT * FROM Books";
SqlCommand Command = new SqlCommand(Query, Icon);
SqlDataAdapter da = new SqlDataAdapter(Command);
DataTable dt = new DataTable();
da.Fill(dt);
BrDataGrid.DataSource = dt;
}
if (cmbAuth.Text == "" && cmbClassi.Text != "")
{
SqlConnection Icon = new SqlConnection(con);
String Query = "SELECT * FROM Books WHERE Classification ='" + cmbClassi.Text + "'"; ;
SqlCommand Command = new SqlCommand(Query, Icon);
SqlDataAdapter da = new SqlDataAdapter(Command);
DataTable dt = new DataTable();
da.Fill(dt);
BrDataGrid.DataSource = dt;
}
if (cmbAuth.Text != "" && cmbClassi.Text == "")
{
SqlConnection Icon = new SqlConnection(con);
String Query = "SELECT * FROM Books WHERE Author ='" + cmbAuth.Text + "'"; ;
SqlCommand Command = new SqlCommand(Query, Icon);
SqlDataAdapter da = new SqlDataAdapter(Command);
DataTable dt = new DataTable();
da.Fill(dt);
BrDataGrid.DataSource = dt;
}
}
This logic:
if (cmbAuth.Text == "" && cmbClassi.Text != "")
{
// build and execute the entire query
}
would lead to an exponential increase in the number of if blocks and a ton of repeated code. Which, of course, is bad.
Instead, build the query once with a linear increase in the number of filters applied. Something logically more like this:
var query = "SELECT * FROM Books WHERE 1 = 1";
var parameters = new List<SqlParameter>();
if (!string.IsNullOrEmpty(cmbAuth.Text))
{
query = query + " AND Author = #Author";
parameters.Add(new SqlParameter("#Author", cmbAuth.Text));
}
// repeat for each input
// then build and execute the connection/command objects from the query and parameters
Basically you build up the query with each condition, then execute the result. As a bonus, this is also using query parameters rather than the current SQL-injectable code you have. You can further add slight improvements to this, such as using a StringBuilder instead of concatenating strings or perhaps using more explicit SQL data types when building the parameter objects, etc.
This would be similar to a commonly used approach in LINQ, where one might have something like this:
var books = db.Books;
if (!string.IsNullOrEmpty(cmbAuth.Text))
books = books.Where(b => b.Author == cmbAuth.Text);
if (!string.IsNullOrEmpty(cmbClassi.Text))
books = books.Where(b => b.Classification == cmbClassi.Text);
// etc.
I am trying to populate a group of labels in a C# windows form with some values that are in a certain attribute (PlayerName) in a database that I have in access.
Currently the only code I have is:
OleDbConnection connection = new OleDbConnection(CONNECTION STRING HERE);
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
command.CommandText = "SELECT PlayerName FROM [TotalPlayerName] WHERE Team = 1 AND SportID = " + Form1.IDNumber;
I need a list or array that holds these values so I can use them to populate the labels, but I am unaware of how to do this.
You need to call ExecuteReader to obtain a data reader and then loop through the rows of the result set like this:
List<string> result = new List<string>();
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
result.Add(reader.GetString(0));
}
}
Before you do this, don't forget to open the connection like this:
connection.Open();
There are a couple of things here..... for sake of best practice well its more standard practice... as I like to say!
Use USING as this cleans up after connection.. see here for great examples in a "using" block is a SqlConnection closed on return or exception?
using (OdbcDataReader DbReader = DbCommand.ExecuteReader())
{
int fCount = DbReader.FieldCount;
while (DbReader.Read())
{
Label1 = DbReader.GetString(0);
Label2 = DbReader.GetString(1);
Label3 = DbReader.GetString(2);
Label4 = DbReader.GetString(3);
for (int i = 0; i < fCount; i++)
{
String col = DbReader.GetString(i);
Console.Write(col + ":");
}
Console.WriteLine();
}
}
NB your SQL only return 1 field /String at the moment
while reading the data fill the list like
List<string> players = new List<string>();
OleDbDataReader rdr = command.ExecuteReader();
While(rdr.Read())
{
players.Add(rdr["PlayerName"].ToString());
}
You need to create a OleDbReader object to read the response from the query. You will also need to create a List to store the data Something like this:
List<string> playerNameList = new List<string>();
using (OleDbReader r = command.ExecuteReader())
{
while(reader.Read())
{
playerNameList.Add(reader.GetString(0));
}
}
One option might be using OleDbDataAdapter to fill a DataTable those values that returns your query;
var dt = new DataTable();
using(var da = new OleDbDataAdapter(command))
{
da.Fill(dt);
}
And since your query return one column, you can use AsEnumerable to that datatable to get them as a string like;
List<string> list = dt.AsEnumerable()
.Select(r => r.Field<string>("PlayerName"))
.ToList();
You can read: Queries in LINQ to DataSet
By the way, you should always use parameterized queries. This kind of string concatenations are open for SQL Injection attacks.
Also use using statement to dispose your connection and command automatically as I did for OleDbDataAdapter in my example.
Hi all, please I need your help, I am trying to execute a query and put all the retrieved data in a data set, but I get this error "cannot implicitly convert type 'int' to 'system.data.dataset'"
Here's the code:
// this is a small piece of the sql
String Astra_conn = ConfigurationManager.ConnectionStrings["AstraSeverConnection"].ConnectionString;
System.Text.StringBuilder sql = new System.Text.StringBuilder();
sql.Append(" SELECT ROWNUM AS ID, institution, LPAD (a.zone_name, 3, '0') AS campus, ");
sql.Append(" term_name AS term, student_instance_id AS student_id, subject, course, ");
sql.Append(" section_name AS section_num, offering AS title, ");
//Its OracleConnection because it is an Oracle server otherwise, it would be SqlConnection.
DataSet rs = new DataSet();
OracleConnection Astra_db_Conn = new OracleConnection(Astra_conn);
string myquery = sql.ToString();
OracleCommand cmd = new OracleCommand(myquery);
Astra_db_Conn.Open();
try
{
SqlDataAdapter adpt = new SqlDataAdapter();
rs = cmd.ExecuteNonQuery(); // this is where is get the error.
adpt.Fill(rs);
}
catch(Exception e)
{
log.Error("*** ERROR *** IRISExportQueries.loadStudentInfoLearningSites():" + e);
}
I've also tried
Astra_db_Conn.Open();
try
{
SqlDataReader reader = new SqlDataAdapter();
reader = cmd.ExecuteNonQuery(); // this is where is get the error.
}
catch(Exception e)
{
log.Error("*** ERROR *** IRISExportQueries.loadStudentInfoLearningSites():" + e);</pre>
}
Then I get the error: "cannot implicitly convert type 'int' to 'System.Data.SqlClient.SqlDataReader'"
Thanks your help will be very much appreciated.
The problem is that ExecuteNonQuery returns the number of affected rows (an integer) and not a DataSet or DataReader. I'm afraid you're not using ADO.NET components correctly.
These 2 lines are enough to fill a DataSet
SqlDataAdapter adpt = new SqlDataAdapter(cmd);
adpt.Fill(rs);
In any case this is not your only problem, you're mixing Sql* ADO.NET components with Oracle*ones. Adapter should be OracleDataAdapter
OracleDataAdapter adpt = new OracleDataAdapter(cmd);
adpt.Fill(rs);
Something else: you're never assigning the connection to the command. You should do
OracleCommand cmd = new OracleCommand(myquery, Astra_db_Conn);
And at last but not least important, dispose every instance of classes implementing IDisposable interface, otherwise unmanaged resources as connections to datasase won't be released.
This is the final version applying all my suggestions
var rs = new DataSet();
string myquery = sql.ToString();
using (var Astra_db_Conn = new OracleConnection(Astra_conn))
using (var cmd = new OracleCommand(myquery, Astra_db_Conn))
using (var adpt = new OracleDataAdapter(cmd))
{
Astra_db_Conn.Open();
adpt.Fill(rs);
}
The method ExecuteNonQuery() returns an int with the number of rows that are affected by the command.
To access the data from the query you should see this existing answer: Direct method from SQL command text to DataSet.
SqlDataAdapter adapt= new SqlDataAdapter(cmd.CommandText,cmd.Connection);
adapt.Fill(rs, " Your Table name as it is in database inside this quotation");
now u can give source to ur data views like datalist or datatable or gridview as following
Datalist1.DataSource= rs.Tables("Your Table name as it is in database inside the above q mark")
now atlast jst bind it
Datalist1.DataBind();
Is it possible to connect to a local MDB file and pick a single bit of info out of it ?
I have a table in a .mbd file with a single bit of info in it. I would like to have that record be output into a disabled textbox for a reference. I believe I can get the DB open, and run the query but no idea what I need to read from it.
thanks
var myDataTable = new DataTable();
using (var conection = new OleDbConnection("Provider=Microsoft.JET.OLEDB.4.0;" + "data source=C:\\menus\\newmenus\\menu.mdb;Password=****"))
{
conection.Open();
var query = "Select siteid From n_user";
var adapter = new OleDbDataAdapter(query, conection);
OleDbCommandBuilder oleDbCommandBuilder = new OleDbCommandBuilder(adapter);
}
To simply read a single field on your database table you could use an OleDbDataReader that could loop over the result and return the field required..
var myDataTable = new DataTable();
using (var conection = new OleDbConnection("Provider=Microsoft.JET.OLEDB.4.0;" + "data source=C:\\menus\\newmenus\\menu.mdb;Password=****"))
{
conection.Open();
var query = "Select siteid From n_user";
var command = new OleDbCommand(query, conection);
var reader = command.ExecuteReader();
while(reader.Read())
textBox1.Text = reader[0].ToString();
}
if you have just one record and just one field then a better solution is the method ExecuteScalar
conection.Open();
// A query that returns just one record composed of just one field
var query = "Select siteid From n_user where userid=1";
var command = new OleDbCommand(query, conection);
int result = (int)command.ExecuteScalar(); // Supposing that siteid is an integer
Probably I should also mention that ExecuteScalar returns null if the query doesn't find a match for the userid, so it is better to be careful with the conversion here
object result = command.ExecuteScalar();
if( result != null)
int userID = (int)result;
.....
Yes very possible. Just have the adapter fill the DataTable, also I don't think you'll need the OleDbCommandBuilder.
using (var conection = new OleDbConnection("Provider=Microsoft.JET.OLEDB.4.0;" + "data source=C:\\menus\\newmenus\\menu.mdb;Password=****"))
{
conection.Open();
var query = "Select siteid From n_user";
var adapter = new OleDbDataAdapter(query, conection);
adapter.Fill(myDataTable);
myTextBox.Text = myDataTable.Rows[0][0].ToString();
}
Also I think using ExecuteScalar would be a better solution, but my answer was tailored to the objects you had already instantiated.
You could use OleDbCommand.ExecuteScalar to retrieve a single value. It is returned as an object and you could cast it to the correct type.
Are you looking for stm like this?
OleDbCommand cmd = new OleDbCommand();
OleDbDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
// read ur stuff here.
}