Combining 2 queries into 1 struct - c#

I have 2 different databases and I need to get results of their queries into 1 structure:
struct my_order
{
public int Id_N
public int OrderId;
public string Discount;
public string CustomerId;
public string ShipAddress;
}
My queries:
my_order ret = new my_order();
SqlConnection con = open_sql(firstDB);
string firstQuery= #" SELECT OrderId, Discount FROM Orders
WHERE Id = " + id_n.ToString(); //some ID that I got earlier
SqlCommand command = new SqlCommand(firstQuery, con);
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
ret.Id_N = id_n;
ret.OrderId = reader["OrderId"].ToString();
ret.Discount = reader["Discount"].ToString();
}
SqlConnection second_con = open_sql(secondDB);
string secondQuery= #" SELECT CustomerId, ShipAdress FROM Details
WHERE Id = " + id_n.ToString();
//id_n - some ID that I got earlier(the same as in the first query)
SqlCommand secondCommand = new SqlCommand(secondQuery, second_con);
SqlDataReader secondReader = secondCommand.ExecuteReader();
while (secondReader.Read())
{
ret.Id_N = id_n;
ret.CustomerId = secondReader["CustomerId"].ToString();
ret.ShipAddress = secondReader["ShipAddress"].ToString();
}
The problem is that compiler get the result from the firstQuery and doesn't from the secondQuery. It doesn't get into while(secondReader.Read()).
How to correct it?
PS: I change the code and queries a little bit, because my is too big, but the question is the same.
Regards,
Alexander.

Shooting into the blue here without an error or a more detailed description of what is going wrong, but you have a typo in your code:
string secondQuery= #" SELECT CustomerId, ShipAdress FROM Details WHERE Id = " + id_n.ToString();
ret.ShipAddress= secondReader["ShipAddress"].ToString();
You are writing ShipAdress with one and 2 d's.
Choose the correct version

The reason why it doesn't go into the while (secondReader.Read()) { ... } is because the second query does not return any rows, because there are no rows in table Details with the specified Id value.

you may use the propriete HasRows and IsDBNull(columnIndex) method to check if it contains data
if (secondReader.HasRows)
// Get data
else
//there is no data

Related

How can I find my product_id without using datareader?

My variable names, database tables are right, I get error like this;
MySql.Data.MySqlClient.MySqlException: 'There is already an open DataReader associated with this Connection which must be closed first.'
public string urun_adi_bul(string urun_id)// find product name
{
if (genel.baglanti.State == ConnectionState.Closed)
{
genel.baglanti.Open();
}
string urun_adi = "";
genel.sqlgonder.Connection = genel.baglanti;
genel.sqlgonder.CommandText = "Select * from urunler where urun_id="+urun_id;
MySqlDataReader oku = genel.sqlgonder.ExecuteReader();
while (oku.Read())
{
urun_adi = oku["urun_id"].ToString();
}
oku.Close();
return urun_adi;// product name
}
public void hesapGetir(ListView lvSiparis, string masa_id)
{
genel.baglanti.Open();
MySqlCommand sqlgonder = new MySqlCommand();
sqlgonder.Connection = genel.baglanti;
sqlgonder.CommandText = "Select * from adisyonlar where masa_id = "+masa_id;
MySqlDataReader oku = sqlgonder.ExecuteReader();
lvSiparis.Items.Clear();
string urun_adi = "",urun_id="";
while (oku.Read())
{
urun_id = oku["urun_id"].ToString();
decimal fiyat = Convert.ToDecimal(urun_fiyati_bul(urun_id)); // price
decimal adet = Convert.ToDecimal(oku["urun_adet"]); // piece
decimal toplam = fiyat * adet; // total
urun_adi = urun_adi_bul(urun_id);
ListViewItem item = new ListViewItem(urun_adi);
item.SubItems.Add(adet.ToString());
item.SubItems.Add(toplam.ToString());
lvSiparis.Items.Add(item);
}
oku.Close();
genel.baglanti.Close();
}
How can I use 2 datareaders in a loop?
You can have only one open reader (or any kind of query) per connection. But you actually only need one reader if you combine the two queries with a JOIN:
SELECT adisyonlar.urun_id, urun_adet, urunler.urun_id
FROM adisyonlar
LEFT JOIN urunler
ON adisyonlar.urun_id = urunler.urun_id
This way you let the db do the work to find the matching records, and you only need one query instead of asking the db again and again for every row in adisyonlar.
Note that it's better practice to explicity name the columns you want to fetch instead of fetching all columns with SELECT *.
Plus: your queries are open to SQL injection! Please use parameterized queries.

Retrieve multiple items of data from database into one single label

I want to retrieve multiples values from database and display on one label.
My database design currently is:
courseid scholarshipid course
--------------------------------
1 1 maths
2 1 english
3 1 science
scholarshipid schName
-----------------------
1 moon
2 start
3 light
I would like to retrieve this information into one single label such as
Maths, English, Science
However, now I manage to retrieve one of it which is just maths.
This is my code in code behind:
protected void btnShowDetails_Click(object sender, EventArgs e)
{
string Selectedid = GVFBAcc.SelectedRow.Cells[1].Text;//get user id
int selectedIdtoPass = Convert.ToInt32(Selectedid);
courseBLL getRecord = new courseBLL();
addcourse courseRetrieve = new addcourse();
courseRetrieve = getRecord.getCourseDetail(selectedIdtoPass);
lbCourse.Text = courseRetrieve.course1 + "," + courseRetrieve.course1;
}
in my courseBLL
public addcourse getCourseDetail(int idcourse)
{
addcourse userObj = new addcourse();
courseDAL objtoPass = new courseDAL();
userObj = objtoPass.displayCourseInfo(idcourse);
return userObj;
}
in my DAL
public addcourse displayCourseInfo(int idcourse)
{
string strCommandText = "Select course from course where schokarshipid = #schokarshipid";
SqlCommand cmd = new SqlCommand(strCommandText, conn);
cmd.Parameters.AddWithValue("#scholarshipid", idcourse);
conn.Open();
SqlDataReader myReader = cmd.ExecuteReader();
addcourse userObj = new addcourse();
while (myReader.Read())
{
int sID = Convert.ToInt32(myReader["courseID"].ToString());
string course = myReader["course"].ToString();
userObj = new addcourse(sID, course);
}
myReader.Close();
return userObj;
}
Edited:
public addcourse displayCourseInfo(int idcourse)
{
var courses = new List<addcourse>();
string strCommandText = "Select statement here"
SqlCommand cmd = new SqlCommand(strCommandText, conn);
cmd.Parameters.AddWithValue("#scholarshipid", idcourse);
conn.Open();
SqlDataReader myReader = cmd.ExecuteReader();
while (myReader.Read())
{
int sID = Convert.ToInt32(myReader["scholarshipid"].ToString());
string course = myReader["course"].ToString();
courses.Add(new addcourse(sID,course));
}
myReader.Close();
return courses;
}
I have removed some fields for this purpose so that I will not confuse you
You should return a List<addcourse> from getCourseDetail() and from displayCourseInfo and then you can do this if your addCourse has Course property:
lbCourse.Text = string.Join(", ", courses.Select(x => x.Course));
If the property name is different then change x.Course to that.
So in your reader you will do this
var courses = new List<addcourse>();
while (myReader.Read())
{
int sID = Convert.ToInt32(myReader["courseID"].ToString());
string course = myReader["course"].ToString();
courses.Add( new addcourse(sID, course)) ;
}
return courses;
Your query is also wrong:
Select course, from course ss inner join where courseID =#courseID
So you should fix that and make sure you get the columns you need because right now it is only getting course column and it has syntax errors. Run your query directly against the db using management studio. Once your query works the copy paste it and replace where part with a parameter the way you have it right now.
EDIT
It seems you are still stuck with this so I will give you a more detailed answer; however, you should really study up on some fundamental programming concepts. Anyhow, here it is:
Your code behind:
protected void btnShowDetails_Click(object sender, EventArgs e)
{
string Selectedid = GVFBAcc.SelectedRow.Cells[1].Text;//get user id
// Make sure this is the scholarshipid or the whole thing will
// not work.
int selectedIdtoPass = Convert.ToInt32(Selectedid);
courseBLL courseRetriever = new courseBLL();
// Remember you will get a list here
List<addcourse> courses = courseRetriever.getCourseDetail(selectedIdtoPass);
// This will take the list and separate the course property with a comma and space
var courseNames = string.Join(", ", courses);
// Now assign it to the text property
lbCourse.Text = courseNames;
}
Your BLL:
// See here you are retuning a list
// But you need to pass the scholarshipid so you can get the courses for that scholarshipid
public List<addcourse> GerCourses(int scholarshipId)
{
courseDAL courseRetriever = new courseDAL();
// Get the list
List<addcourse> courses = courseRetriever.GetCourses(scholarshipId);
return courses;
}
Your DAL:
// See here you are retuning a list
// But you need to pass the scholarshipid so you can get the courses for that scholarshipid
public List<addcourse> GetCourses(int scholarshipId)
{
// Make sure your query is correct, see you have spelling mistakes
// it should be scholarshipid not schokarshipid. it has to match the column in your database
// Make sure your table is called course and it has 3 columns: 1. courseid 2. course
// 3. scholarshipid or this query will not work
string strCommandText = "Select courseid, course from course where scholarshipid = #scholarshipId";
SqlCommand cmd = new SqlCommand(strCommandText, conn);
cmd.Parameters.AddWithValue("#scholarshipid", scholarshipId);
conn.Open();
SqlDataReader myReader = cmd.ExecuteReader();
// create a list so we can hold all the courses
List<addcourse> userObjs = new List<addcourse>();
// This will read one row at a time so keep reading until there are no more records
while (myReader.Read())
{
int sID = Convert.ToInt32(myReader["courseid"].ToString());
string course = myReader["course"].ToString();
addcourse userObj = new addcourse(sID, course);
// add it to the list
userObjs.Add(userObj);
}
myReader.Close();
// return the list
return userObjs;
}
A few more tips:
Give your methods more meaningful names. See the names I gave them GetCourses, now it reads like English and it is easy to follow.
Your class addcourse should be called Course. addcourse sounds like an action "add course", that could be a good name for a method if you were adding courses. Also use Pascal notation for class names and method names. Use Camel casing for arguments, parameters and local variables.
Learn how to use the Visual Studio debugger. Go watch some YouTube videos on Visual Studio Debugger.
Create a for loop then add it on the variable you are using

how to convert a data type avoiding System.FormatException?

Im trying to receive a string an convert it in integer, the code is this:
int menu = 3
int orden = 0;
string query = #"select max(oppord)+1 as orden
from rhlibry.vaoppfi
where pincor = " + menu;
OdbcConnection cn = new OdbcConnection("dsn=RHLIBRY;uid=PC00;pwd=PC00;");
OdbcCommand cmd = new OdbcCommand(query, cn);
cn.Open();
OdbcDataReader oa = cmd.ExecuteReader();
while (oa.Read())
{
orden = Int32.Parse(oa["orden"].ToString());
}
return orden;
the sql query return "orden" in string format, and I need transform it to integer.
The line orden = Int32.Parse(oa["orden"].ToString()); returns a error of type System.FormatException.
Why? I do wrong?
Help me please !
Thanks
This is probably because your query returns null value.
Suppose you have a Category table that have an Id column with values 1,2,3.
If you run this query:
SELECT Max(Id)+1 As Id From Category WHERE Id = -1
You will receive this result:
Id
----------
NULL
So when you use Int32.Parse(oa["Id"].ToString()) you will receive a FormatException.
As a fix you can use:
SELECT ISNULL(Max(Id),0)+1 As Id From Category WHERE Id = -1
Also if your business logic allows, you can remove criteria.
Also in C# side, you can use int.TryParse():
int id = 0;
var idObject= oa["Id"];
if (idObject!=null)
int.TryParse(oa["Id"].ToString(), out id);

How to count cart using session user

I am currently working on a project on a shopping cart. I already done the cart but somehow I cannot count the cart and it keep shows 0. I already check that the session for the user is grabbed.
This is the method I used:
//check cart count
public int getCartCount(string Username)
{
MySql.Data.MySqlClient.MySqlConnection msqlConnection = null;
msqlConnection = new MySql.Data.MySqlClient.MySqlConnection("server=localhost;User Id=root;password=rootPassw0rd;Persist Security Info=False;database=infosec;Integrated Security=False");
MySql.Data.MySqlClient.MySqlCommand msqlCommand = new MySql.Data.MySqlClient.MySqlCommand();
//define the connection used by the command object
msqlCommand.Connection = msqlConnection;
msqlCommand.CommandText = "SELECT COUNT(*) FROM shoppingcart WHERE Item_Id = #Username ";
msqlCommand.Parameters.AddWithValue("#Username", _Username);
msqlConnection.Open();
string nofRow = "";
MySql.Data.MySqlClient.MySqlDataReader msqlReader = msqlCommand.ExecuteReader();
if (msqlReader.Read())
{
nofRow = msqlReader["COUNT(*)"].ToString();
}
msqlConnection.Close();
msqlConnection.Close();
msqlReader.Dispose();
int cart = Convert.ToInt32(nofRow);
return cart;
This is the code behind for the .axps page:
//cart increase if there items added.
if (Session["customer_Username"] == null)
{
cartCount.InnerText = "Cart (0)";
}
else
{
cartBLL cBLL = new cartBLL();
string a = Session["customer_Username"].ToString();
int count = cBLL.getCartCount(a);
cartCount.InnerText = "Cart (" + count + ")";
}
Hope you all can help me find the problems.
Thanks in advanced.
Change this line :
nofRow = msqlReader["COUNT(*)"].ToString();
To
nofRow = msqlReader[0].ToString();
Perhaps, it helps you.
Well, maybe MySqlDataReader can have a problem with reading of "COUNT(*)" column (I have not tried yet).
Another point, when you read "COUNT(*)" column with msqlReader["COUNT(*)"], your result can be null and Convert.ToInt32(null) generates 0. (But this is very unlikely)
But more important, using MySqlDataReader is not a good choice in your case. Since you using COUNT(*) to get row counts, ExecuteScalar is a better choice which returns first column of first row in your query.
msqlCommand.CommandText = "SELECT COUNT(*) FROM shoppingcart WHERE Item_Id = #Username ";
msqlCommand.Parameters.AddWithValue("#Username", _Username);
int cart = (int)msqlCommand.ExecuteScalar();
Also use using statement to dispose your MySqlConnection and MySqlCommand like;
using(MySqlConnection msqlConnection = new MySqlConnection(conString))
using(MySqlCommand msqlCommand = myCon.CreateCommand())
{
//
}
Few things:
Verify that string a = Session["customer_Username"].ToString(); does return the username.
Change nofRow = msqlReader["COUNT(*)"].ToString(); to nofRow = msqlReader[0].ToString();. Your query has the count aggregate function in it.
Verify that SELECT COUNT(*) FROM shoppingcart WHERE Item_Id = #Username does pull in value. #Username needs to be replaced by the value that you have from the session.
Looks like you have a typo in this line msqlCommand.Parameters.AddWithValue("#Username", _Username);. _Username should be Username.

SQL select from database in C#

I have the following code in C#:
string query = "SELECT * FROM Zboruri WHERE cod_aeroport = " + country;
using (var command = new SqlCommand(query, connection))
{
var list = new ArrayList();
var reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
string data1 = reader.GetString(1);
string data2 = reader.GetString(2);
list.Add(cod_aeroport);
list.Add(data1);
list.Add(data2);
}
}
else
{
string raspuns = "nu este info";
list.Add(raspuns);
}
reader.Close();
connection.Close();
return list;
}
My database table has these columns:
data1(numeric(18,0))
data2(numeric(18,0))
...........
and it giving me error:
Index was outside the bounds of the array.
on this line of code:
string data2 = reader.GetString(2);
How can I fix error?
index starts at 0, not 1
string data1 = reader.GetString(0);
string data2 = reader.GetString(1);
I'll prefer to use the column names retrieve from the table because it gives more description than using index of the column (which is usually the reason for index out of bounds exception)
ex,
string data1 = reader["colName1"].ToString();
string data2 = reader["colName2"].ToString();
side-note: please do use parameters in your query,
string query = "SELECT * FROM Zboruri WHERE cod_aeroport = #country";
and before you call ExecuteReader add this line,
command.Parameters.AddWithValue("#country", country);
var reader = command.ExecuteReader();
The index is zero based, so the first column is 0, the second is 1. You should really use the named version of the columns though;
string data1 = reader["data1"].ToString();
One more thing, you should probably parameterize your query to avoid SQL injection problems, in this case it's almost as simple as your original query and much safer. It also helps the database save quite a bit of time and memory on similar queries;
string query = "SELECT * FROM Zboruri WHERE cod_aeroport = #country";
using (var command = new SqlCommand(query, connection))
{
command.Parameters.AddWithValue("#country", country);
var list = new ArrayList();
...
You should better access them by name, by resolving the index by name using the GetOrdinal() method first, so that the code doesn't break if the query is extended later.
if (reader.HasRows)
{
int data1Index = reader.GetOrdinal("data1");
int data2Index = reader.GetOrdinal("data2");
while (reader.Read())
{
string data1 = reader.GetString(data1index);
string data2 = reader.GetString(data2index);
list.Add(cod_aeroport);
list.Add(data1);
list.Add(data2);
}
}
Note that this is the slightly better approach compared to using the named indexer because it avoids looking up the index on every row.
Also, please do parametrize the query to avoid SQL injection.

Categories

Resources