I'm retrieving some information from an MSSQL via SQLDataReader, but while debugging it I notice in some cases the reader clears the result view with the error "Enumeration yielded no results" see the screenshot Before Running passing Read(),
After passing read()
this is my code,the error happens on getActiveUsers() method.
getDatabases() works just fine. could someone help me? cheers
public partial class automation : System.Web.UI.Page
{
SqlConnection con;
static List<ActiveUsers> activeUsers = new List<ActiveUsers>();
protected void Page_Load(object sender, EventArgs e)
{
ASPxGridView1.DataSource = activeUsers.ToList();
}
public List<ActiveUsers> getDatabases()
{
//passing query
string SqlQuery = "SELECT [WorkspaceName],[MaConfig_Customers].Name FROM [MaConfig_CustomerDatabases] INNER JOIN [MaConfig_Customers] ON [MaConfig_CustomerDatabases].CustomerId = [MaConfig_Customers].CustomerId where [MaConfig_Customers].Status = 0";
//creating connection
string sqlconn = ConfigurationManager.ConnectionStrings["MaxLiveConnectionString"].ConnectionString;
con = new System.Data.SqlClient.SqlConnection(sqlconn);
var cmd = new SqlCommand(SqlQuery, con);
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
List<ActiveUsers> results = new List<ActiveUsers>();
if (reader.Read())
{
while (reader.Read())
{
ActiveUsers company = new ActiveUsers();
company.DatabaseName = String.Format("{0}", reader["WorkspaceName"]);
company.ClientName = String.Format("{0}", reader["Name"]);
results.Add(company);
}
}
con.Close();
return results;
}
public void getActiveUsers()
{
activeUsers.Clear();
List<ActiveUsers> Databases= getDatabases();
SqlConnection conn = new SqlConnection();
string SqlQuery = "select [disabled], [ADMN_Users1].[Record_Id] ,[ADMN_Users].[User_Id] from admn_Users1 inner join [ADMN_Users] on [ADMN_Users1].[record_Id] = [ADMN_Users].[Record_Id] Where [disabled] & 0x2 = 0 ";
for (int i = 0;i < Databases.Count;i++)
{
conn.ConnectionString =
"Data Source=MAXSQLCLUS01;" +
"Initial Catalog=" + Databases[i].ToString()+";"+
"User id=sa;" +
"Password=Max1m1zer;";
var cmd = new SqlCommand(SqlQuery, conn);
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
int NumberOfUsersCounter = 0 ;
//TODO Select Enabled users
if (reader.Read())
{
while (reader.Read())
{
string user = String.Format("{0}", reader["User_Id"]);
//logic to remove system users
if (user.Equals("master", StringComparison.CurrentCultureIgnoreCase))
{
}
else
if (user.Equals("emailuser", StringComparison.CurrentCultureIgnoreCase))
{
}
else
if (user.Equals("webuser", StringComparison.CurrentCultureIgnoreCase))
{
}
else
{
NumberOfUsersCounter++;
}
}
ActiveUsers newEntry = new ActiveUsers();
newEntry.NumberActiveUsers = NumberOfUsersCounter.ToString();
newEntry.DatabaseName = Databases[i].DatabaseName.ToString();
newEntry.ClientName = Databases[i].ClientName.ToString();
activeUsers.Add(newEntry);
}
conn.Close();
//Add to ActiveUsers list
}
ASPxGridView1.AutoGenerateColumns = true;
ASPxGridView1.DataSource = activeUsers.ToList();
ASPxGridView1.DataBind();
}
protected void ASPxButton1_Click(object sender, EventArgs e)
{
getActiveUsers();
}
protected void btnExportExcel_Click(object sender, EventArgs e)
{
ASPxGridView1.DataBind();
ASPxGridViewExporter1.Landscape = true;
ASPxGridViewExporter1.FileName = "User Count Report";
ASPxGridViewExporter1.WriteXlsToResponse();
}
}
}
if (reader.Read())
{
while (reader.Read())
{
ActiveUsers company = new ActiveUsers();
company.DatabaseName = String.Format("{0}", reader["WorkspaceName"]);
company.ClientName = String.Format("{0}", reader["Name"]);
results.Add(company);
}
}
use this
if (reader.HasRows)
{
while (reader.Read())
{
ActiveUsers company = new ActiveUsers();
company.DatabaseName = String.Format("{0}", reader["WorkspaceName"]);
company.ClientName = String.Format("{0}", reader["Name"]);
results.Add(company);
}
}
your if Condition is wrong
if(reader.Read()) ==> is Wrong
Read() is not return boolean Value
use HasRows to check rows in SQLDataReader
You are skipping the first result. if (reader.Read()) { while(reader.Read()) {.... Remove the enclosing if, all it does is see if there is a row and retrieve it but then you do not read it, instead you do it again in the if so the first result is always discarded.
public List<ActiveUsers> getDatabases()
{
//passing query
string SqlQuery = "SELECT [WorkspaceName],[MaConfig_Customers].Name FROM [MaConfig_CustomerDatabases] INNER JOIN [MaConfig_Customers] ON [MaConfig_CustomerDatabases].CustomerId = [MaConfig_Customers].CustomerId where [MaConfig_Customers].Status = 0";
//creating connection
string sqlconn = ConfigurationManager.ConnectionStrings["MaxLiveConnectionString"].ConnectionString;
using(con = new System.Data.SqlClient.SqlConnection(sqlconn))
using(var cmd = new SqlCommand(SqlQuery, con))
{
con.Open();
using(SqlDataReader reader = cmd.ExecuteReader())
{
List<ActiveUsers> results = new List<ActiveUsers>();
while (reader.Read())
{
ActiveUsers company = new ActiveUsers();
company.DatabaseName = reader.GetString(0);
company.ClientName = reader.GetString(1);
results.Add(company);
}
}
}
return results;
}
Side notes:
company.DatabaseName = String.Format("{0}", reader["WorkspaceName"]) would be better written as company.DatabaseName = reader.GetString(0). The same goes for the next line. No need to use string.Format and you are specifying the columns and order in the query so use the ordinal index so get the native value.
I would recommend you wrap the SqlConnection and SqlDataReader in using blocks to ensure they are closed/disposed after use even in the event of an exception.
Related
It only can be called once. where did I gone wrong? The second time it executes, no text appears. The Login and Site.Master are two different partial classes. I am kind of confounded on how to solve this.
Login.aspx
public partial class Login : System.Web.UI.Page
{
SqlDataReader dR;
DatabaseMgmt drObj = new DatabaseMgmt();
protected void Page_Load(object sender, EventArgs e)
{
}
protected void submitButton_Click(object sender, EventArgs e)
{
string strEmail, strPwd;
int intShopperID;
strEmail = txtEmail.Text.ToLower();
strPwd = txtPwd.Text.Trim();
string strSqlCmd = "SELECT ShopperID FROM Shopper WHERE Email ="+ "'" + strEmail + "'" + "AND Passwd ="+ "'"+ strPwd + "'";
dR = drObj.ExecuteSelect(strSqlCmd);
if(dR.Read())
{
intShopperID = Convert.ToInt32(Session["ShopperID"]);
Session["ShopperID"]=intShopperID;
Response.Redirect("Default.aspx");
}
else
{
intShopperID = 0;
lblMsg.Text = "Incorrect email or password";
lblMsg.ForeColor = System.Drawing.Color.Red;
}
dR.Close();
}
}
Site.Master
public partial class Site : System.Web.UI.MasterPage
{
DatabaseMgmt dBObj = new DatabaseMgmt();
protected void Page_Load(object sender, EventArgs e)
{
if (Session["ShopperID"] != null)
{
string strSqlCmd;
strSqlCmd = "SELECT Name FROM Shopper WHERE ShopperID = " + Session["ShopperID"];
lblWelcome.Text = "Welcome Eric";
logoutButton.Visible = true;
loginButton.Visible = false;
regButton.Visible = false;
}
else
{
logoutButton.Visible = false;
loginButton.Visible = true;
regButton.Visible = true;
lblWelcome.Text = "";
}
}
Display Welcome Message
First Run
Second Run
database
I did not see where you are reading the ShopperID from the database. Perhaps that is your issue. ???
To address the Parameterisation issue, I think you should consider something more like this:
public int GetShopperID(System.String strEmail, System.String strPwd) {
int result = 0;
string strSqlCmd = "SELECT ShopperID FROM Shopper WHERE Email = #Email AND Passwd = #Passwd";
using (var cmd = new System.Data.SqlClient.SqlCommand(strSqlCmd, new System.Data.SqlClient.SqlConnection(_databaseConnection))) {
cmd.Parameters.Add("#Email", System.Data.SqlDbType.VarChar, 50);
cmd.Parameters.Add("#Passwd", System.Data.SqlDbType.VarChar, 50);
cmd.Parameter["#Email"].Value = strEmail;
cmd.Parameter["#Passwd"].Value = strPwd;
cmd.Connection.Open();
using (var reader = cmd.ExecuteReader()) {
if (reader.Read()) {
result = Convert.ToInt32(reader["ShopperID"]);
}
}
}
return result;
}
First, it appears you close your connection, however you don't have an explicit open connection (unless you didn't include that line by mistake) which on a postback your query won't produce results since the connection is closed after you run it the first time. Second, confirm you don't have your code in a !Page.IsPostBack, which could also cause it not to appear. Finally you can do all that you are trying to do using one datareader instead of opening up two datareaders with this:
string strEmail = txtEmail.Text.ToLower();
string strPwd = txtPwd.Text.Trim();
string conString = ConfigurationManager.ConnectionStrings["YourConnection"].ConnectionString;
using (SqlConnection con = new SqlConnection(conString))
{
using (SqlCommand cmd = new SqlCommand("SELECT ShopperID, Name FROM Shopper WHERE Email = #Email AND Passwrd = #Passwrd", con))
{
con.Open();
cmd.Parameters.AddWithValue("#Email", strEmail);
cmd.Parameters.AddWithValue("#user_name", strPwd);
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
if (dr.HasRows)
{
if(dr["ShopperID"].ToString() != Session["ShopperID"].ToString())
{
Response.Redirect("~/default.aspx");
}
else if (dr["ShopperID"].ToString() == Session["ShopperID"].ToString())
{
lblWelcome.Text = "Welcome " + dr["Name"].ToString();
}
else
{
lblMsg.Text = "Incorrect email or password";
lblMsg.ForeColor = System.Drawing.Color.Red;
}
}
}
con.Close();
}
}
This also addresses the SQL injection by using Type-Safe SQL Parameters, which was outlined as an issue in other comments.
I am trying to use a SqlDataReader to run queries on two tables where the 1st column in the Selection table is a foreign key referencing to the Items table, and then display the results in labels, but I keep getting the error:
Invalid attempt to read when no data is present.
Here is my code:
public partial class Read : System.Web.UI.Page
{
SqlConnection conn = new SqlConnection(#"data source = localhost; integrated security = true; database = dev_handin1");
SqlCommand cmd = null;
SqlDataReader rdr = null;
string sqlsel = "SELECT MainItemId FROM Selection";
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GetInfo();
}
}
private void GetInfo() {
try
{
cmd = new SqlCommand(sqlsel, conn);
conn.Open();
sqlsel = "SELECT * FROM Items WHERE ItemId = MyMainItem";
rdr = cmd.ExecuteReader();
var MyMainItem = rdr[0];
while (rdr.Read())
{
LabelCategory1.Text = rdr[1].ToString();
LabelHeadline1.Text = rdr[2].ToString();
LabelText1.Text = rdr[3].ToString();
LabelJoke1.Text = rdr[4].ToString();
}
}
catch (Exception ex)
{
LabelMessage1.Text = ex.Message;
}
finally
{
rdr.Close();
conn.Close();
}
}
}
}
I'm pretty new at this so please bear with me.
I've got a problem with some queries from c# to SQL. I need to have a query executeReader and inside of it a if else that allow me to choose between two inserts queries. I'm calling a little external program(with the URL collected into the db) which allows me to choose between 1 and 2, if the 1 is chosen(pass) else(fail). I can't do that because the debug is giving me:
'A Command is yet associated with a DataReader opened, which needs to be closed.'
I don't know what to try anymore.
private void btnSTART_Click(object sender, RoutedEventArgs e)
{
sqliteCon.Open();
if (sqliteCon.State == System.Data.ConnectionState.Open)
{
string path = null;//estrazione1
SqlCommand cmd = new SqlCommand("select nomeI FROM tabL where selection=1", sqliteCon);
SqlDataReader nomeIRdr = null;//estrazione2
//qui
var scriptsToRun = new List<string>();
using (nomeIRdr = cmd.ExecuteReader())
{
while (nomeIRdr.Read())//estrazione4
{
path = nomeIRdr["nomeI"].ToString();//estrazione5
Process MyProc = Process.Start(path);//permette la run del path contenuto nel db
MyProc.WaitForExit();
var exitCode = MyProc.ExitCode;
if (exitCode == 1)
{
scriptsToRun.Add("insert into tabL resItem values 'PASS'");
}
else
{
scriptsToRun.Add("insert into tabL resItem values 'FAIL'");
}
sqliteCon.Close();
}
}
foreach (var script in scriptsToRun)
{
SqlCommand cmd1 = new SqlCommand(script, sqliteCon);
cmd1.ExecuteNonQuery();
}
}
}
Do not share single connection and cram everything into a single routine. Please, keep your code simple.
Create (and Dispose) Connection whenever you query RDBMS
Extract methods
Code:
Process execution and return execution results collection:
// Item1 - path
// Item2 - true in succeed
private List<Tuple<string, bool>> ExecuteResults() {
List<Tuple<string, bool>> result = new List<Tuple<string, bool>>();
using (var con = new SqlConnection(ConnectionStringHere)) {
con.Open();
string sql =
#"select nomeItem
from tabList
where selection = 1";
using (SqlCommand cmd = new SqlCommand(sql, con)) {
using (var reader = cmd.ExecuteReader()) {
while (reader.Read()) {
string path = Convert.ToString(reader[0]);
using (Process process = Process.Start(path)) {
process.WaitForExit();
result.Add(Tuple.Create(path, process.ExitCode == 1));
}
}
}
}
}
return result;
}
Saving results in RDBMS
private void ApplyExecuteResults(IEnumerable<Tuple<string, bool>> results) {
using (var con = new SqlConnection(ConnectionStringHere)) {
con.Open();
string sql =
#"update tabList
set resItem = #prm_resItem
where nomeItem = #prm_nomeItem";
using (SqlCommand cmd = new SqlCommand(sql, con)) {
cmd.Parameters.Add("#prm_nomeItem", SqlDbType.VarChar);
cmd.Parameters.Add("#prm_resItem", SqlDbType.VarChar);
foreach (var item in results) {
cmd.Parameters[0].Value = item.Item1;
cmd.Parameters[1].Value = item.Item2 ? "PASS" : "FAIL";
cmd.ExecuteNonQuery();
}
}
}
}
Finally, combine both routines:
private void btnSTART_Click(object sender, RoutedEventArgs e) {
ApplyExecuteResults(ExecuteResults());
}
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
Ontrip _ontrip = new Ontrip(_FNAME);
string _query2 = "select CContactno from CustomerTbl where CUsername = #USERNAME";
string _query3 = "select Price from TransactionTypeTble T join PendingTransTbl P ON P.TransType = T.TransType ";
string _query4 = "select VehicleDescription from DriverTbl D join VehicleSpecTbl V ON D.VehicleType = V.VehicleType";
SqlConnection _sqlcnn = new SqlConnection("Data Source=MELIODAS;Initial Catalog=WeGo;Integrated Security=True");
_sqlcnn.Open();
try
{
SqlDataReader _reader = null;
SqlCommand _cmd = new SqlCommand("Select CFName+' '+CLName from CustomerTbl where CUsername=#USERNAME", _sqlcnn);
SqlParameter _param = new SqlParameter();
_param.ParameterName = "#USERNAME";
_param.Value = dataGridView1.Rows[e.RowIndex].Cells[1].Value.ToString();
_cmd.Parameters.Add(_param);
_reader = _cmd.ExecuteReader(); //for displaying users name in the label
while (_reader.Read())
{
_ontrip._txtboxUsername.Text = _reader.GetString(0);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
using (SqlCommand _sqlcmd = new SqlCommand(_query2, _sqlcnn))
{
try
{
SqlDataReader _reader = null;
SqlParameter _param = new SqlParameter();
_param.ParameterName = "#USERNAME";
_param.Value = dataGridView1.Rows[e.RowIndex].Cells[1].Value.ToString();
_sqlcmd.Parameters.Add(_param);
_reader = _sqlcmd.ExecuteReader(); //for displaying users name in the label
while (_reader.Read())
{
_ontrip._txtboxContact.Text = _reader.GetString(0);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
Is their a way for me to read the query and display the output, when i run this code their is an error saying that their is already an open data reader associated with the command. I should be displaying multiple data in a textbox
try Call Close when done reading.
_reader.Close();
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
Ontrip _ontrip = new Ontrip(_FNAME);
string _query2 = "select CContactno from CustomerTbl where CUsername = #USERNAME";
string _query3 = "select Price from TransactionTypeTble T join PendingTransTbl P ON P.TransType = T.TransType ";
string _query4 = "select VehicleDescription from DriverTbl D join VehicleSpecTbl V ON D.VehicleType = V.VehicleType";
SqlConnection _sqlcnn = new SqlConnection("Data Source=MELIODAS;Initial Catalog=WeGo;Integrated Security=True;MultipleActiveResultSets=True ");
_sqlcnn.Open();
I added MultipleActiveResultSet or MARS
I wanted to read all data from a table(containg 3 rows) and to add all the data into generic collection.From collection i wana bind to gridview.
The code displayed below works but only last row is displayed 3 times in gridview.Can You help me.Am a beginer
protected void Page_Load(object sender, EventArgs e)
{
List<Student> listid = new List<Student>();
Student stud = new Student();
SqlConnection con = new SqlConnection("........");
string sql = "select * from StudentInfo";
con.Open();
SqlCommand cmd = new SqlCommand(sql, con);
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
stud.Studid = Convert.ToInt32(dr["StudId"]);
stud.StudName = dr["StudName"].ToString();
stud.StudentDept = dr["StudentDept"].ToString();
listid.Add(stud);
}
GridView1.DataSource = listid;
GridView1.DataBind();
}
public class Student
{
private int studid;
public int Studid
{
get { return studid; }
set { studid = value; }
}
private string studName;
public string StudName
{
get { return studName; }
set { studName = value; }
}
private string studentDept;
public string StudentDept
{
get { return studentDept; }
set { studentDept = value; }
}
The output is like this:
You need to instantiate your object inside while loop
Otherwise you will have same data in the collection
So the code should be
protected void Page_Load(object sender, EventArgs e)
{
List<Student> listid = new List<Student>();
SqlConnection con = new SqlConnection("........");
string sql = "select * from StudentInfo";
con.Open();
SqlCommand cmd = new SqlCommand(sql, con);
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
Student stud = new Student();
stud.Studid = Convert.ToInt32(dr["StudId"]);
stud.StudName = dr["StudName"].ToString();
stud.StudentDept = dr["StudentDept"].ToString();
listid.Add(stud);
}
GridView1.DataSource = listid;
GridView1.DataBind();
}
Also it is not a good practice to use while to data reader or directly open connection
You should use using statement.
using(SqlConnection con = new SqlConnection("connection string"))
{
con.Open();
using(SqlCommand cmd = new SqlCommand("SELECT * FROM SomeTable", connection))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader != null)
{
while (reader.Read())
{
//do something
}
}
} // reader closed and disposed up here
} // command disposed here
} //connection closed and disposed here
In the DataReader while loop instantiate a new Student for each row in the database table:
while (dr.Read())
{
var stud = new Student();
stud.Studid = Convert.ToInt32(dr["StudId"]);
stud.StudName = dr["StudName"].ToString();
stud.StudentDept = dr["StudentDept"].ToString();
listid.Add(stud);
}