I am running a stored procedure and the result is this format
+------+--------+-----+-------+
| ID | Resign | Sum | Count |
+------+--------+-----+-------+
| 1234 | 0 | 400 | 3 |
| 1234 | 1 | 800 | 4 |
+------+--------+-----+-------+
I tried this code to reference the values returned by the query but, it seem not working the way I want it
if (conn.State != ConnectionState.Open)
conn.Open();
SqlCommand sc = new SqlCommand();
sc.CommandText = "usp_GetResignPool";
sc.CommandType = CommandType.StoredProcedure;
sc.Connection = conn;
sc.Parameters.Add(AddParam(EndDate, "#EndDate"));
sc.Parameters.Add(AddParam(am_id, "#id"));
SqlDataReader reader;
reader = sc.ExecuteReader();
while (reader.Read())
{
if reader. // lost here
}
How can I do something like this. ↓
int resigned = 0, resign_count = 0, not_resigned = 0, notresign_count =0;
if (read["Resigned"] == 1)
{
resigned = read["sum"];
resign_count = read["count"];
}
else
{
not_resigned = read["sum"];
notresign_count = read["count"];
}
It is not important that I used SQLDataReader.
Edit: Real column names
ID Resigned sum count
--------- ----------- ---------------------- -----------
It didn't work because you don't have a column in your table named "Resigned", like you have when you are working with your SqlDataReader.
EDIT: I think the root of the problem is the way you are adding parameters. AddParam() is not the method you want to be using. Therefore, your result set is probably empty.
....
SqlCommand sc = new SqlCommand();
sc.CommandText = "usp_GetResignPool";
sc.CommandType = CommandType.StoredProcedure;
sc.Connection = conn;
sc.Parameters.AddWithValue("#EndDate", EndDate);
sc.Parameters.AddWithValue("id", am_id);
SqlDataReader reader;
reader = sc.ExecuteReader();
using (reader = sc.ExecuteReader())
{
while (reader.Read())
{
if (Convert.ToInt32(read["Resign"]) == 1)
{
resigned = Convert.ToInt32(read["Sum"]);
resign_count = Convert.ToInt32(read["Count"]);
}
else
{
not_resigned = Convert.ToInt32(read["Sum"]);
notresign_count = Convert.ToInt32(read["Count"]);
}
}
}
Notice how I changed your element indicator to "Resign". This needs to match the column that is returned in your dataset. Or, you could use a column number to get this, like so:
if (Convert.ToInt32(read[1]) == 1)
{
resigned = Convert.ToInt32(read[2]);
resign_count = read[3];
}
else
{
not_resigned = Convert.ToInt32(read[2]);
notresign_count = Convert.ToInt32(read[3]);
}
Also, keep in my that in every iteration or your while loop, you'll be overwriting the variables resigned, resign_count or not_resigned and notresign_count.
Would this work?
int resign = 0;
int not_resign = 0;
int resign_count = 0;
int not_resign_count = 0;
while (reader.Read())
{
if (Convert.ToInt32(reader["Resigned"]) == 1)
{
resign = Convert.ToInt32(reader["Sum"]);
resign_count = Convert.ToInt32(reader["Count"]);
}
else
{
not_resign = Convert.ToInt32(reader["Sum"]);
not_resign_count = Convert.ToInt32(reader["Count"]);
}
}
Can you post your query from the procedure?
Are the column names really "Sum" and "Count"?
There are reserved words, maybe you should try using "AS" and give other names to these to columns in the projection.
Related
Table Form
I'm trying to filter this table with RadioButton when DateDePublication is Checked and the value of the search text equals for example 2000 table should return all books who have DateDePublication equals to 2000
this is Search Button code :
private void RechBtn_Click(object sender, EventArgs e)
{
dataGridView1.DataSource = repository.GetAllLivres(rechtext.Text);
}
and search method code to return all books :
public List<Livre> FilterDateDePublication(string date)
{
using (var connection = factory.CreateConnection())
{
var livres = new List<Livre>();
connection.ConnectionString = connectionString;
connection.Open();
var command = factory.CreateCommand();
command.Connection = connection;
command.CommandText = "select * from livre where date_publication like '%" + date + "%'";
using (DbDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Livre l = new Livre();
l.Isbn = reader["isbn"].ToString();
l.Titre = reader["titre"].ToString();
l.DatePublication = DateTime.Parse(reader["date_publication"].ToString());
l.NombrePage = Int32.Parse(reader["nombre_page"].ToString());
l.Couverture = reader["couverture"].ToString();
l.Prix = Double.Parse(reader["nombre_page"].ToString());
l.QuantiteDisponible = Int32.Parse(reader["quantite_disponible"].ToString());
}
}
return livres;
}
your function GetAllLivres just looks for books with a specifc string in their title.
command.CommandText = "select * from livre where titre like '%" + mc + "%'";
You should change that to search on the pub date. Can says how that should look because we dont know your database scheme.
By the way , do not build SQL like that, its a huge security hole. Use parametrized queries
I know i have 4 radio buttons when one of them is checked Search function should look up by each of radio button.
Well again not seeing the UI its hard to say but my guess is you have something like this
|-search by: --------| <<< group box
| ( ) Author | << radio buttons
| ( ) title |
| (*) Year |
----------------------
Search for :_________________: <<== text box
[Start Search] <<== button
I hope so.
So do this
if(radioYear.Checked){
FilterDateDePublication(searchText.Text);
}
else if(radioAuthor.Checked)
.......
Note that the date the user enters might not match the format of the date in the database, in that case you need to do some massaging
I would however refactor your code, you have surely noticed that 90% of your FilterDateDePublication is the same as the title one.
You should do
public List<Livre> ReadBooks(string query)
{
using (var connection = factory.CreateConnection())
{
var livres = new List<Livre>();
connection.ConnectionString = connectionString;
connection.Open();
var command = factory.CreateCommand();
command.Connection = connection;
command.CommandText = query;
using (DbDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Livre l = new Livre();
l.Isbn = reader["isbn"].ToString();
l.Titre = reader["titre"].ToString();
l.DatePublication = DateTime.Parse(reader["date_publication"].ToString());
l.NombrePage = Int32.Parse(reader["nombre_page"].ToString());
l.Couverture = reader["couverture"].ToString();
l.Prix = Double.Parse(reader["nombre_page"].ToString());
l.QuantiteDisponible = Int32.Parse(reader["quantite_disponible"].ToString());
}
}
return livres;
}
and then have
List<Livre> GetByDate(string date){
return GetBooks("select * from livre where date_publication like '%" + date + "%'";
}
even better would be to use sql parameters. I will update this answer later
This is my table on MySQL database :
+----------+--------+---------+
| UserName | Region | UsercIX |
+----------+--------+---------+
| a123456 | X410 | NULL |
| a123456 | X420 | 1 |
| a123456 | X430 | NULL |
| a123456 | X440 | 1 |
+----------+--------+---------+
The user a123456 is write enabled for X420 and X440 Region (UsercIX=1) and reading for X410 and X430 Region (UsercIX=NULL).
I need to find in this table -via LINQ or your suggestion- only values equals to 1 in the column UsercIX, because with DataReader extracting the first value of the column which is null.
Please an you help me ?
My code below
using (OdbcDataReader reader = command.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
int UsercIX = Convert.ToInt32(reader["UsercIX"]); //IS NULL
}
}
}
Edit #01
using (OdbcDataReader reader = command.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
int UsercIX = reader.GetInt32(6);
}
}
}
May i suggest doing a try parse on the value?
int number;
bool success = Int32.TryParse((reader["UsercIX"], out number);
if (success)
{
// it worked, yay
}
else
{
// 😥
}
I think you should access the values in this way:
**SqlDataReader** reader = command.ExecuteReader();
int UsercIX = reader.GetInt32(2);
with in the while loop.
The colums start with 0
Eventually you run in an error when accesing Null-value then use a try() {} catch() {} structure to avoid this.
- Hope this helps!
Here is a complete example for mysql;
public void CreateMySqlDataReader(string mySelectQuery, MySqlConnection myConnection)
{
MySqlCommand myCommand = new MySqlCommand(mySelectQuery, myConnection);
myConnection.Open();
MMySqlDataReader myReader;
myReader = myCommand.ExecuteReader();
try
{
while(myReader.Read())
{
Console.WriteLine(myReader.GetString(0));
}
}
finally
{
myReader.Close();
myConnection.Close();
}
}
I have this table called WeeklySales with 2 columns, DateandTime and Sales. Now, I have 3 textbox on my form. I wanted to get the latest value that was added on the table so I have this string.
string sql = "SELECT Sales FROM database.weeklysales ORDER BY DateandTime DESC LIMIT 3";
Now, I have this database(lets say that month is the date),
DateandTime | Sales
March | $300
February | $500
January | $400
and get this result with that string:
Sales
$300
$500
$400
Now, I wanted to put the first row into first textbox, then second row to second textbox and so on... Now, I do not know what to out in inside the Datareader...
try
{
con.Open();
using (reader = cmd.ExecuteReader())
{
first.Text = ?
second.Text = ?
third.Text = ?
}
}
finally
{
con.Close();
}
I have searched but they only get the first row unfortunately.
Since you only have 3 text boxes to fill - no loop just advance the reader manually.
MySqlDataReader dr = cmd.ExecuteReader();
dr.Read();
first.Text = dr.GetValue(0).ToString();
dr.Read();
second.Text = dr.GetValue(0).ToString();
dr.Read();
third.Text = dr.GetValue(0).ToString();
The SqlDataReader class has a Read() method, which returns a bool as long as there are more rows to read. You can use it to read multiple rows using a while loop for example.
using (SqlDataReader reader = cmd.ExecuteReader()
{
while (reader.Read())
{
//Do your stuff here
}
}
See https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.read%28v=vs.110%29.aspx for further information
Following code will be helpful to you,
using (reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
int i = 1;
while (reader.Read())
{
switch (i)
{
case 1:
first.Text = reader["Sales"].ToString();
break;
case 2:
second.Text = reader["Sales"].ToString();
break;
default:
third.Text = reader["Sales"].ToString();
break;
}
i += 1;
}
}
}
Avoiding repetitions or in case of multiple objects
public void Example(MySqlDataReader dr)
{
TextBox a = new TextBox();
TextBox b = new TextBox();
TextBox c = new TextBox();
foreach(TextBox current in new List<TextBox> { a, b, c })
{
dr.Read();
current.Text = dr.GetValue(0).ToString();
}
}
I have been trying a more efficient way to get and set data from my database in mysql to a variable. I've used a for loop to shorten the code and make it easier to read, though i can't think of a way to properly set other variables. Here's my code:
Note: I use 18 different local variables. (i.g ad, mnd, psk, pck, etc..)
for (int i = 1; i <= 18; i++) {
MySqlCommand cmd = dbConn.CreateCommand();
cmd.CommandText = "SELECT price from products where productID = '" + i + "'";
MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read()) {
ad = Convert.ToInt32(reader.ToString());
}
}
I am trying to retrieve the prices of 18 products from the database, but on this piece of code, I can only set one price. Any kind of help would be appreciated.
You assign all prices to 1 variable. Your code run like this
ad = 150; //sample price
ad = 240;
ad = 100;
...(18 times)
You have to use array instead of single variable.
Change your code to :
MySqlCommand cmd = dbConn.CreateCommand();
cmd.CommandText = "SELECT price from products where productID > 1 AND productID < 19" ;
MySqlDataReader reader = cmd.ExecuteReader();
int counter = 0;
while (reader.Read()) {
ad[counter++] = Convert.ToInt32(reader.ToString());
}
Okay, change your schema a bit, so you have
name | price | id
------------------------
'ad' 1.00 1
'mnd' 42.24 2
'psk' 6.66 3
'pck' 2.00 4
'etc' 9999.99 5
...
Then use Dapper like this,
using Dapper;
...
IDictionary<string, decimal> products;
using(var connection = new SqlConnection(GetConnectionString()))
{
connection.Open();
products = connection.Query("SELECT name, price FROM products;")
.ToDictionary(
row => (string)row.Name,
row => (decimal)row.Price);
}
then you can get whatever product you want like this,
var adPrice = products["ad"];
Once you have many products (a lot more than 18) you won't want to hold them all in memory at once but for now this would work well.
I am getting the error, and not sure how to fix it. When I change the SQL command to another query, it seems to work (with the same amount of data, 10 rows). Ideas? Note: I am aware I should be using parameters in my SQL command, i am just testing.
SqlCommand getLabsCommand = new SqlCommand("SELECT labGrade FROM labStudent WHERE studentID = '"+Label1.Text+"' ");
getLabsCommand.Connection = conn;
ArrayList alMakers = new ArrayList();
conn.Open();
SqlDataReader dr = getLabsCommand.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
//alMakers.Add(dr.GetString(1));
alMakers.Add(dr.GetInt32(1));
}
}
string[] labsList = (string[])alMakers.ToArray(typeof(string));
for(int i = 0; i < alMakers.Count; i++)
{
TextBox labs = new TextBox();
labs.ID = "lab" + i;
form1.Controls.Add(labs);
labs.Text = labsList.GetValue(i).ToString();
}
dr.Close();
conn.Close();
}
The function above should be putting these values in each textbox.
25
25
25
25
20
22
25
10
15
16
You are only selecting one column (SELECT labGrade FROM...); indexing is 0-based, so only GetInt32(0) is defined. GetInt32(1) refers to the second column (the first column is index 0, second column is index 1, etc). You probably want:
alMakers.Add(dr.GetInt32(0));
This type of thing is where tools like dapper shine, btw:
var alMakers = conn.Query<int>(
"SELECT labGrade FROM labStudent WHERE studentID = #id",
new { id = Label1.Text }).AsList();