public MyUniversity GetDepartmentsByDepartmentID(string department)
{
string query = "SELECT * FROM Departments WHERE DepartmentID ='" + department + "'";
SqlConnection connection = new SqlConnection(dbConnection);
SqlCommand command = new SqlCommand(query, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
MyUniversity deprtmnt = new MyUniversity();
while (reader.Read())
{
deprtmnt.code = reader["Code"].ToString();
deprtmnt.title = reader["title"].ToString();
deprtmnt.credit = reader["Credit"].ToString();
deprtmnt.description = reader["Description"].ToString();
deprtmnt.semester = reader["Semester"].ToString();
reader.Close();
connection.Close();
return deprtmnt;
}
}
Your error is that not all code path return value. Reason is that in the scope of your loop:
while (reader.Read())
{
/* Code */
return deprtmnt;
}
If code doesn't enter while loop then there is no return statement.
move the return to be outside of the loop's scope:
MyUniversity deprtmnt = new MyUniversity();
while (reader.Read())
{
/* Code */
}
return deprtmnt;
Read about parameterized queries as using string concatenation for sql queries is susceptible for sql-injections
Why do we always prefer using parameters in SQL statements?
Related
I'm trying to write the id request from the database. This is how I wrote it:
public int QueryId(String query)
{
var temp = this.connection;
MySqlCommand verifica = new MySqlCommand(query, connection);
var queryResult = verifica.ExecuteScalar();
return Convert.ToInt32(verifica.ExecuteScalar());
}
This is how I make use of the function:
MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
nomeCorrente = reader.GetString("nome");
cognomeCorrente = reader.GetString("cognome");
idCorrente = db.QueryId("SELECT id FROM thewishlist.user WHERE email='" + user.Text + "'");
}
reader.Close();
db.CloseConnection();
It does not generate errors, but when I run the project and log out the user gives me the following error:
MySql.Data.MySqlClient.MySqlException There is already an open DataReader associated with this Connection which must be closed first.
The error is pretty clear. I suggest you make use of using statement and also since you're only returning one column you and use ExcecuteScalar instead of ExecuteReader. So your code will look something like:
var id = 0;
var query = "SELECT ID FROM thewishlist.user WHERE email = #email";
using (var con = new SqlConnection(this.connection))
{
using (var cmd = new SqlCommand(query, con))
{
con.Open();
cmd.Parameters.Add("#email", SqlDbType.NVarChar).Value = user.Text;
id = (int)cmd.ExecuteScalar();
}
}//connection will auto close here and object will get disposed
return id;
Also to prevent sql injection you should always use paramertised sql queries.
As Jason said that, you should close the reader firstly, then call db.QueryId to execute the new query, I modifed your code as follows:
using (MySqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
nomeCorrente = reader.GetString("nome");
cognomeCorrente = reader.GetString("cognome");
}
reader.Close();
}
idCorrente = db.QueryId("SELECT id FROM thewishlist.user WHERE email='" + user.Text + "'");
db.CloseConnection();
I am trying to display pictures from my SQLSEVER database on my website. My users have a picture field with a picture datatype. If the picture column is null, then I want the picture displayed to be a egg.jpg, but right now for every person their picture is egg.jpg, even if they have a picture in the database. Here is my method.
public string getImageUrl()
{
System.Data.SqlClient.SqlConnection sc = new System.Data.SqlClient.SqlConnection();
sc.ConnectionString = "Server =MRCOMPUTER2\\SQLEXPRESS; Database = WBL;Trusted_Connection=Yes;";
sc.Open();
System.Data.SqlClient.SqlCommand insert = new System.Data.SqlClient.SqlCommand();
insert.Connection = sc;
insert.CommandText = "SELECT profilePicture from SystemUser";
insert.ExecuteNonQuery();
SqlDataReader reader = insert.ExecuteReader();
string url = "";
while (reader.Read())
{
if ( !DBNull.Value.Equals(reader[0]))
{
url = "data:Image / png; base64," + Convert.ToBase64String((byte[])reader[0]);
}
else {
url = "images/egg.jpg";
}
}
return url;
}
Your code returns the image for the last user in your table.
Here:
insert.CommandText = "SELECT profilePicture from SystemUser";
you select all users from the table (not just the one you currently show). Then:
while (reader.Read())
{
...
url = ...
...
}
you re-assign url inside every iteration of your while loop. This is semantically equivalent to:
url = ... /* The value determined from the last record of the reader. */
Thus, all your users show the same image - the one of the last user in your table.
You SELECT statement is attached into a ExecuteNonQuery?
Take it off.
Just perform the READER statement...
Try this:
static void Main(string[] args)
{
string connectionString = "Server=.;Database=AA;Trusted_Connection=True;";
/*
CREATE TABLE [dbo].[SystemUser]
(
[ProfilePicture] [varbinary](max) NULL
)
*/
using (SqlConnection connection = new SqlConnection(connectionString))
{
string sql = #"
INSERT [AA].[dbo].[SystemUser] ([ProfilePicture]) VALUES (#ProfilePicture);
INSERT [AA].[dbo].[SystemUser] ([ProfilePicture]) VALUES (NULL);
";
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandText = sql;
command.CommandType = CommandType.Text;
byte[] bytes = File.ReadAllBytes(#"1.jpg");
command.Parameters.AddWithValue("#ProfilePicture", bytes);
connection.Open();
command.ExecuteNonQuery();
}
DataSet ds = new DataSet();
using (SqlConnection connection = new SqlConnection(connectionString))
{
string sql = #"
SELECT TOP 1000 [ProfilePicture] FROM [AA].[dbo].[SystemUser];
";
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandText = sql;
command.CommandType = CommandType.Text;
connection.Open();
SqlDataAdapter da = new SqlDataAdapter(command);
da.Fill(ds);
}
var rows = ds.Tables[0].Rows.Cast<DataRow>();
foreach (DataRow row in rows)
{
byte[] bytes = row.Field<byte[]>(0);
if (bytes != null)
{
string fileName = Guid.NewGuid().ToString("N") + ".jpg";
File.WriteAllBytes(fileName, bytes);
}
}
}
Can you try using the name of the column such as
var Val = (String)reader["column name"];
Also, try something like this to test:
while (reader.Read())
{
var testVal = reader.GetString(0);
Var testVal2 = reader.GetString(1);
I have error in this code. What should happen is if I have two stall in the database, the stall price must be doubled, but what happened in this code is if I have two stall in the database, the stall price isn't doubled and if I only have one stall the stall price is 0.
public double GetStallPrice(int commtaxno)
{
try
{
string query = "SELECT * FROM contract_details WHERE comm_tax_no = " + commtaxno;
DatabaseString myConnectionString = new DatabaseString();
OleDbConnection connection = new OleDbConnection();
connection.ConnectionString = myConnectionString.connect();
connection.Open();
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
command.CommandText = query;
OleDbDataReader stallReader = command.ExecuteReader();
stallReader.Read();
while(stallReader.Read())
{
try
{
string query2 = "SELECT section_ID FROM specific_stall WHERE stall_no = '" + stallReader["stall_no"].ToString() + "'";
OleDbCommand command2 = new OleDbCommand();
command2.Connection = connection;
command2.CommandText = query2;
OleDbDataReader sectionReader = command2.ExecuteReader();
sectionReader.Read();
sectionid = Convert.ToInt32(sectionReader["section_ID"].ToString());
try
{
string query3 = "SELECT stall_price FROM stall_sections WHERE section_ID = " + sectionid;
OleDbCommand command3 = new OleDbCommand();
command3.Connection = connection;
command3.CommandText = query3;
OleDbDataReader stallPriceReader = command3.ExecuteReader();
stallPriceReader.Read();
stall_price = Convert.ToDouble(stallPriceReader["stall_price"].ToString());
}
catch (Exception c)
{
MessageBox.Show(c.GetBaseException().ToString());
}
}
catch (Exception b)
{
MessageBox.Show(b.GetBaseException().ToString());
}
sum_stall_price = sum_stall_price + stall_price;
}
connection.Close();
}
catch (Exception a)
{
MessageBox.Show(a.GetBaseException().ToString());
}
return sum_stall_price;
}
I think the error is here:
stallReader.Read();
while(stallReader.Read())
You read first record and then read the second, without processing the first.
You have to remove first row and leave just
while(stallReader.Read())
As a side note, you should try to always use using syntax with classes that implement IDisposable interface. So, just an example:
using (OleDbConnection connection = new OleDbConnection())
{
// All the code inside
}
In this way you're sure that the object is properly released.
Finally: do not compose queries manually, but use parameters instead!!
Using parameters can avoid SQL injection and many headaches due to numeric (float, double, currency) and dates conversion!!
public Users GetUserById(string _id)
{
MySqlConnection conn = new MySqlConnection(connstr);
conn.Open();
string sql = ("select * from Books where id = " + _id);
MySqlCommand cmd = new MySqlCommand(sql, conn);
MySqlDataReader reader = cmd.ExecuteReader();
Users obj = new Users();
if (reader.Read())
{
obj.id = Convert.ToInt32(reader[0]);
obj.UserName = reader[1].ToString();
}
reader.Close();
conn.Close();
return obj;
}
I am puuling the info in Json Format but
Out Put for this is: {"UserName":"John","id":1}
Expected Out put is: [{"UserName":"John","id":1}]
I am missing the Square braces for the record
Whats the problem with my code?
Your expected output i.e. [{"UserName":"John","id":1}]
represents the List of Users object.
So if you want such output should return from your function then you just need to return a List of user from your function.
But as your function name GetUserById, I think it should return single user( So I don't know why are trying to return an array of users from this)
But anyway you can get the expected output in this way
public List<Users> GetUserById(string _id)
{
MySqlConnection conn = new MySqlConnection(connstr);
conn.Open();
string sql = ("select * from Books where id = " + _id);
MySqlCommand cmd = new MySqlCommand(sql, conn);
MySqlDataReader reader = cmd.ExecuteReader();
List<Users> users=new List<Users>();
Users obj = new Users();
if (reader.Read())
{
obj.id = Convert.ToInt32(reader[0]);
obj.UserName = reader[1].ToString();
users.Add(obj);
}
reader.Close();
conn.Close();
return users;
}
Now whenever this users convert into json format, it will return the expected output.
I forget to return value in single tier application.
public int Studentid()
{
try
{
SqlConnection con = new SqlConnection(connectionStr);
SqlCommand cmd = new SqlCommand("SELECT s_id FROM student where name = + ('" + Request.QueryString.ToString() + "')", con);
con.Open();
SqlDataReader dr = null;
con.Open();
dr = cmd.ExecuteReader();
if (dr.Read())
{
//Want help hear how I return value
}
con.Close();
}
catch (Exception ex)
{
throw ex;
}
}
Here is a version of your method that achieves what you're after.
public int GetStudentId()
{
var sql = string.Format("SELECT s_id FROM student where name = '{0}'", Request.QueryString);
using (var con = new SqlConnection(connectionStr))
using (var cmd = new SqlCommand(sql, con))
{
con.Open();
var dr = cmd.ExecuteReader();
return dr.Read() ? return dr.GetInt32(0) : -1;
}
}
There's no need to use try/catch when you don't do anything with the exception except re-throw (and in fact you were losing the original stack trace by using throw ex; instead of just throw;. Also, the C# using statement takes care of cleaning up your resources for you in fewer lines of code.
IMPORTANT
Passing the query string directly into SQL like that means that anyone can execute random SQL into your database, potentially deleting everything (or worse). Read up on SQL Injection.
You should use using blocks, so that you are sure that the connection, command and reader are closed correctly. Then you can just return the value from inside the if statement, and doesn't have to store it in a variable until you have closed the objects.
You only have to open the connection once.
You should use parameterised queries, instead of concatenating values into the query.
public int Studentid() {
try {
using (SqlConnection con = new SqlConnection(connectionStr)) {
using (SqlCommand cmd = new SqlCommand("SELECT s_id FROM student where name = #Name", con)) {
cmd.Parameters.Add("#Name", DbType.VarChar, 50).Value = Request.QueryString.ToString();
con.Open();
using (SqlDataReader dr = cmd.ExecuteReader()) {
if (dr.Read()) {
return dr.GetInt32(0);
} else {
return -1; // some value to indicate a missing record
// or throw an exception
}
}
}
}
} catch (Exception ex) {
throw; // just as this, to rethrow with the stack trace intact
}
}
The easiest way to return a single value is to call ExecuteScalar. You should also fix your SQL injection bug. And did you mean to encode the entire query string array, or just to pick out a single value?
public int StudentId()
{
string sql = "SELECT s_id FROM student WHERE name = #name";
using (var con = new SqlConnection(connectionStr))
{
using (var cmd = new SqlCommand(sql, con))
{
cmd.Parameters.Add("#name", DbType.VarChar, 256).Value = Request.QueryString["name"];
con.Open();
return (int)cmd.ExecuteScalar();
}
}
}
try this:
int s_id = (int) dr["s_id"];
int studId=0;
if(rdr.Read())
{
studId=rdr.GetInt32(rdr.GetOrdinal("s_id"));
}
if (dr.Read())
{
//Want help hear how i return value
int value = dr.GetInt32("s_id");
}
Like this?
public int Studentid()
{
int studentId = -1;
SqlConnection con = null;
try
{
con = new SqlConnection(connectionStr);
SqlCommand cmd = new SqlCommand("SELECT s_id FROM student where name = + ('" + Request.QueryString.ToString() + "')", con);
SqlDataReader dr = null;
con.Open();
dr = cmd.ExecuteReader();
if (dr.Read())
{
studentId = dr.GetInt32(0);
}
dr.Close();
}
catch (Exception ex)
{
throw ex;
}
finally
{
if(con != null)
con.Close();
con = null;
}
return studentId;
}