Cannot reuse open DataReader - c#

I am writing a c# windows forms application and i am coming accross the error mentioned above. I think this is happening because i am opening an sql connection and reader object in my main form load object and then doing the same thing again in another click event handler. I am not sure what i need to do in order to change my code / stop this from happening (or if this is even the problem). I have tried turning MARS on in my connection string but this did not fix the problem. Below is my code.
namespace Excel_Importer
{
public partial class Export : Form
{
public Export()
{
InitializeComponent();
}
private void cmbItemLookup_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void Export_Load(object sender, EventArgs e)
{
string connectionString = ConfigurationManager.ConnectionStrings ["dbconnection"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
SqlCommand cmd = new SqlCommand("Select * From ExportItem", conn);
SqlDataReader rdr;
rdr = cmd.ExecuteReader();
System.Data.DataTable dt = new System.Data.DataTable();
dt.Columns.Add("ExportItemName", typeof(string));
dt.Load(rdr);
cmbItemLookup.DisplayMember = "ExportItemName";
cmbItemLookup.DataSource = dt;
conn.Close();
}
}
private void btnLoad_Click(object sender, EventArgs e)
{
string connectionString = ConfigurationManager.ConnectionStrings["dbconnection"].ConnectionString;
SqlConnection conn = new SqlConnection(connectionString);
conn.Open();
SqlCommand cmd2 = new SqlCommand("Select * from " + cmbItemLookup.Text, conn);
SqlDataReader rdr2;
rdr2 = cmd2.ExecuteReader();
try
{
SqlDataAdapter ada = new SqlDataAdapter();
ada.SelectCommand = cmd2;
DataTable dt = new DataTable();
ada.Fill(dt);
BindingSource bs = new BindingSource();
bs.DataSource = dt;
dgvExport.DataSource = bs;
ada.Update(dt);
conn.Close();
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message);
}
}
}
}

You need to close your DataReaders. They implement the IDisposable interface, so the simplest thing is to put them inside a using block:
using (rdr = cmd.ExecuteReader())
{
..
} // .NET always calls Dispose() for you here
Actually, you pretty much have to dispose of everything that implements IDisposable, or problems gonna happen.

As the other answer points out, you must tidy up your clicked event code:
private void btnLoad_Click(object sender, EventArgs e)
{
string connectionString = ConfigurationManager.ConnectionStrings["dbconnection"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connectionString) )
{
conn.Open();
using(SqlCommand cmd2 = new SqlCommand("Select * from " + cmbItemLookup.Text, conn) )
{
using(SqlDataReader rdr2= cmd2.ExecuteReader())
{
try
{
SqlDataAdapter ada = new SqlDataAdapter();
ada.SelectCommand = cmd2;
DataTable dt = new DataTable();
ada.Fill(dt);
BindingSource bs = new BindingSource();
bs.DataSource = dt;
dgvExport.DataSource = bs;
ada.Update(dt);
conn.Close();
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message);
}
}
}
}
}

Related

User Control runs SQL Server stored procedure returns DataTable event handler error

I have this user control that runs a stored procedure
public DataTable btnFind_Click(object sender, EventArgs e)
{
UtilitiesClass ru = new UtilitiesClass();
string connectionString = ru.getConnectionString();
DataTable dt = new DataTable();
SqlConnection myConnection = new SqlConnection(connectionString);
try
{
myConnection.Open();
SqlCommand cmd = new SqlCommand("FindCust", myConnection);
cmd.Parameters.AddWithValue("#cust", txtCust.Text.Trim());
cmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter ta = new SqlDataAdapter(cmd);
ta.Fill(dt);
myConnection.Close();
}
catch (Exception x)
{
MessageBox.Show(e.ToString());
}
return (dt);
}
I get an error on this VS generated code:
this.btnFind.Click += new System.EventHandler(this.btnFind_Click);
telling me
'DataTable FindCustControl.btnFind_Click(object, EventArgs)' has the wrong return type.
I don't know where to start. I don't even understand the problem.
You cannot return data table from the event responsible for handling button click.
UPDATE
To return the datatable from the user control to the main form where user control is present, you should implement a custom event in the user control. There is a great article here:
http://www.windowsdevcenter.com/pub/a/dotnet/2002/04/15/events.html
//Generated code
this.btnFind.Click += new System.EventHandler(this.btnFind_Click);
//Button click handler
public void btnFind_Click(object sender, EventArgs e)
{
var resultset = GetData();
//Do whatever with data here
//...
}
//Query database
public DataTable GetData()
{
UtilitiesClass ru = new UtilitiesClass();
string connectionString = ru.getConnectionString();
DataTable dt = new DataTable();
SqlConnection myConnection = new SqlConnection(connectionString);
try
{
myConnection.Open();
SqlCommand cmd = new SqlCommand("FindCust", myConnection);
cmd.Parameters.AddWithValue("#cust", txtCust.Text.Trim());
cmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter ta = new SqlDataAdapter(cmd);
ta.Fill(dt);
myConnection.Close();
}
catch (Exception x)
{
MessageBox.Show(e.ToString());
}
return (dt);
}

Datagridview with query in C#

I have 2 tables in MySql (privacy , lawsuit_under_500) ,
In privacy i have 2 columns (id , nameofcase ) ,
In lawsuit_under_500 4 columns(id,nameofcase,priceone,pricetwo) ,
I make a form with a datagridview and i want to execute this query :
select privacy.id,lawsuit_under_500.id,privacy.nameofcase, lawsuit_under_500.priceone, lawsuit_under_500.pricetwo
From privacy inner join lawsuit_under_500
where lawsuit_under_500.id=5 and privacy.id=1 || lawsuit_under_500.id=1 and privacy.id=2 || lawsuit_under_500.id=10 and privacy.id=3
ORDER BY privacy.id
In the form i have:
public Form55()
{
InitializeComponent();
}
private void Form55_Load(object sender, EventArgs e)
{
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
I have put the tables in my DataSet but I cant figure out how to make it. I tried to make privacyBindingSourse in the datagridview and i added manually 2 buttons for priceone and pricetwo put i cant put the query so i can get the information.
Any ideas/help how to make it ?
BEFORE YOU ANSWER IF YOU HAVE ANY QUESTION PLEASE ASK ME
using MySql.Data.MySqlClient;
MySqlConnection conn = new MySqlConnection("Your MY SQL connection");
MySqlCommand cmd = new MySqlCommand("Your Mysql query");
MySqlDataReader dr=cmd.ExecuteReader();
gridview1.datasource=dr;
gridview1.databind();
// try this also
connectionString = "Your Connection";
connection = new MySqlConnection(connectionString);
if (this.OpenConnection() == true)
{
mySqlDataAdapter = new MySqlDataAdapter("Your Query", connection);
DataSet DS = new DataSet();
mySqlDataAdapter.Fill(DS);
dataGridView1.DataSource = DS.Tables[0];
//close connection
this.CloseConnection();
}
I made it with this way
private void Form56_Load(object sender, EventArgs e)
{
try
{
MySqlConnection cnn = new MySqlConnection("MY CONNECTION");
cnn.Open();
// - DEBUG
// MessageBox.Show("Connection successful!");
MySqlDataAdapter MyDA = new MySqlDataAdapter();
MyDA.SelectCommand = new MySqlCommand("MY QUERY", cnn);
DataTable table = new DataTable();
MyDA.Fill(table);
BindingSource bSource = new BindingSource();
bSource.DataSource = table;
dataGridView1.DataSource = bSource;
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
MessageBox.Show(ex.Message);
Close();
}
}
static public SqlCeConnection OpenSQL()
{
SqlCeConnection cncount = new SqlCeConnection(#"Data Source = " + Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase) + #"\Database.sdf; Password =''");
return cncount;
}
static public DataTable DoSelect( string strSQL)
{
SqlCeConnection cn = OpenSQL();
DataTable dtRetValue = new DataTable();
using (SqlCeDataAdapter da = new SqlCeDataAdapter())
{
using (SqlCeCommand cmd = cn.CreateCommand())
{
cmd.CommandText = strSQL;
da.SelectCommand = cmd;
if (cn.State == ConnectionState.Closed)
{
cn.Open();
}
try
{
//using (SqlCeDataReader reader = da.SelectCommand.ExecuteReader())
SqlCeDataReader metsDr = da.SelectCommand.ExecuteReader();
dtRetValue.Load(metsDr);
return dtRetValue;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error - DoSelect", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
return null;
}
}
}
}
Insert in Button
string sql1 = "YOURE QUERY ";
DataTable dt1 = SQLcode.DoSelect(sql1);
dgvcompany.DataSource = dt1;

Gridview in asp.net C#

I have two dropdownlist, corresponding to the values,gridview should be displayed,,and below is code for it..But i am not getting What's the problem in it!!
protected void ddlstudents_SelectedIndexChanged(object sender, EventArgs e)
{
if (ddlstudents.SelectedIndex > 0)
{
BindData();
}
}
private void BindData()
{
try
{
SQLiteConnection con = new SQLiteConnection("data source=C:\\ITS Database\\its.development.sqlite3");
string strquery = "select topics.name,course_coverages.progress from topics JOIN course_coverages on topics.id=course_coverages.topic_id where course_coverages.student_id=#studentid AND course_coverages.course_id=#courseid";
con.Open();
SQLiteCommand cmd = new SQLiteCommand();
cmd.connection=con;
cmd = con.CreateCommand();
cmd.CommandText = strquery;
cmd.Parameters.AddWithValue("#studentid", ddlstudents.SelectedIndex);
cmd.Parameters.AddWithValue("#courseid", ddlcourse.SelectedValue);
SQLiteDataAdapter ada = new SQLiteDataAdapter(cmd.CommandText, con);
SQLiteCommandBuilder cbl = new SQLiteCommandBuilder(ada);
DataTable dt = new DataTable();
ada.Fill(dt);
GridView1.DataSource = dt;
GridView1.DataBind();
con.Close();
}
catch (SQLiteException)
{
}
}
Any Help Would Be Appreciated!!
Thanks in Advance!!
Learn how to find the problem your self. if the gridview not showing correct data you can debug the application and find where it failed.
you have not given how you bind ddlstudents and ddlcourse , check the values you get for ddlstudents.SelectedIndex and ddlcourse.SelectedValue as you expected or not.
if values are correct, you can run the SQL statement on your database with above values and see the results.
If you really need to find the error, remove the try catch statement from your code,
If you catch the exception, do something with it. otherwise don't.
try this
protected void ddlstudents_SelectedIndexChanged(object sender, EventArgs e)
{
if (ddlstudents.SelectedIndex > 0)
{
BindData();
}
}
private void BindData()
{
try
{
SQLiteConnection con = new SQLiteConnection("data source=C:\\ITS Database\\its.development.sqlite3");
string strquery = "select topics.name,course_coverages.progress from topics JOIN course_coverages on topics.id=course_coverages.topic_id where course_coverages.student_id=#studentid AND course_coverages.course_id=#courseid";
con.Open();
SQLiteCommand cmd = new SQLiteCommand();
cmd.connection=con;
cmd = con.CreateCommand();
cmd.CommandText = strquery;
cmd.Parameters.AddWithValue("#studentid", ddlstudents.SelectedValue);
cmd.Parameters.AddWithValue("#courseid", ddlcourse.SelectedValue);
SQLiteDataAdapter ada = new SQLiteDataAdapter(cmd.CommandText, con);
SQLiteCommandBuilder cbl = new SQLiteCommandBuilder(ada);
DataTable dt = new DataTable();
ada.Fill(dt);
GridView1.DataSource = dt;
GridView1.DataBind();
con.Close();
}
catch (SQLiteException)
{
}
}

Refreshing Gridview After Button Click

on my asp.net project, how can i refresh my gridview immediately after clicking my button.
my button has update codes.here is the codes;
protected void Button3_Click(object sender, EventArgs e)
{
string strSQL = "UPDATE [bilgiler3] SET [HAM_FM] = ISNULL(MON,0)+ISNULL(TUE,0)+ISNULL(WED,0)+ISNULL(THU,0)+ISNULL(FRI,0)+ISNULL(SAT,0)+ISNULL(SUN,0) WHERE [DATE] BETWEEN #DATE1 AND #DATE2 AND WORK_TYPE='OUT'";
string connStr = WebConfigurationManager.ConnectionStrings["asgdb01ConnectionString"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connStr))
{
using (SqlCommand comm = new SqlCommand())
{
comm.Connection = conn;
comm.CommandText = strSQL;
comm.CommandType = CommandType.Text;
comm.Parameters.AddWithValue("#DATE1", Convert.ToDateTime(TextBox1.Text));
comm.Parameters.AddWithValue("#DATE2", Convert.ToDateTime(TextBox2.Text));
try
{
conn.Open();
int i = comm.ExecuteNonQuery();
conn.Close();
if (i > 0)
{
Response.Write(" SUCCESS ");
}
else
{
Response.Write(" ERROR ! ");
}
}
catch (SqlException ex)
{
Response.Write(ex.ToString());
}
}
}
}
you maybe gonna say "you need to bind the data of your gridview" but i couldnt understand the method.
can you help me about it ?
thank you very much.
I would do the following:
DataSet ds = new DataSet();
SqlDataAdapter sda = new SqlDataAdapter();
SqlConnection sc = new SqlConnection("you connection string here Security=True");
private void loadData()
{
try
{
ds.Clear();
SqlCommand sCmd= new SqlCommand("Load your database", sc);
sda.SelectCommand = sCmd;
sda.Fill(ds, "sCmd");
datagrid.DataSource = ds.Tables["sCmd"];
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.ExitThread();
}
}
something for c# beginners Youtube
Add this code on your button click
SqlConnection con = new SqlConnection("Connection string from web config");
DataSet ds = new DataSet();
SqlDataAdapter sda = new SqlDataAdapter("select * from EmployeeTable", con);
con.Open();
sda.Fill(ds ,"Data");
gridview1.datasource=ds.tables[0];
gridview1.DataBind();
private SqlConnection con;
private SqlConnectionStringBuilder str;
private void Form8_Load(object sender, EventArgs e)
{
loadData();
}
private void loadData()
{
str = new SqlConnectionStringBuilder();
str.Provider = "";
str.DataSource = #"source.accdb";
con = new SqlConnection(str.ConnectionString);
dataGridView1.DataSource = fillTable("Select* from yourTable");
}
private DataTable fillTable(string sql)
{
DataTable datatable = new DataTable();
using (SqlDataAdapter da = new SqlDataAdapter(sql, con))
{
da.Fill(datatable);
}
return datatable;
}
then If you want to refresh the table you put the loaddata(); in the event button_Click hope this help,
DataBind your control on success.
if (i > 0)
{
yourGridView.DataSource=YourDataSource;
yourGridView.DataBind();
Response.Write(" SUCCESS ");
}

Question about showing sql server data in a tabbed view

I am creating a inventory app using c# that pulls its info from sql server. I am making it a tabbed view, with each tab representing a different type of item. I have included some of my code, what I am trying to figure is, is there a better way to do this? I dont feel like the way I am doing is right, even though it works. All my queries for each tab are stored procedures. Secondly, How would I insert and update the database through the grid?
public partial class InventoryWindow : Window
{
private InventoryDS InvDS;
private String connString = "server=PC-server;database=Inventory;user=user;password=password";
String sqlString_Routers = InventoryOutputQuery.InventorySummary_Routers();
public InventoryWindow()
{
InitializeComponent();
if (dgDataView != null)
{
SqlConnection con = new SqlConnection(connString);
SqlDataAdapter adpt = new SqlDataAdapter(sqlString_Routers, con);
DataSet ds = new DataSet();
adpt.Fill(ds, sqlString_Routers);
dgDataView.DataContext = ds;
}
}
private void showTaps()
{
String sqlString_Taps = InventoryOutputQuery.InventorySummary_Routers();
SqlConnection con = new SqlConnection(connString);
con.Open();
SqlCommand cmd = new SqlCommand(sqlString_Routers, con);
SqlDataReader dr = cmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dr);
dgDataView.DataContext = dt;
con.Close();
}
private void showPower()
{
String sqlString_Power = InventoryOutputQuery.InventorySummary_Power();
SqlConnection con = new SqlConnection(connString);
con.Open();
SqlCommand cmd = new SqlCommand(sqlString_Power, con);
SqlDataReader dr = cmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dr);
dgDataView.DataContext = dt;
con.Close();
}
private void showSwitches()
{
String sqlString_Switches = InventoryOutputQuery.InventorySummary_Switches();
SqlConnection con = new SqlConnection(connString);
con.Open();
SqlCommand cmd = new SqlCommand(sqlString_Switches, con);
SqlDataReader dr = cmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dr);
dgDataView.DataContext = dt;
con.Close();
}
And below is how i bind it to the grid:
public void BindGrid(string view)
{
switch (view.ToUpper())
{
case "Routers":
showTaps();
break;
case "POWER":
showPower();
break;
case "SWITCHES":
showSwitches();
break;
case "HUBS":
showHubs();
private void tcDataView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
TabItem ti = tcDataView.SelectedItem as TabItem;
if (ti != null)
BindGrid(ti.Header.ToString());
}
break;
My suggestion is to be careful with how we handle SqlConnection. It is a scarce resource and it will run out pretty soon if we are not careful.
Please wrap sql code in a using block, for example:
using (SqlConnection con = new SqlConnection(connString))
{
SqlDataAdapter adpt = new SqlDataAdapter(sqlString_Routers, con);
DataSet ds = new DataSet();
adpt.Fill(ds, sqlString_Routers);
dgDataView.DataContext = ds;
}
The following link will explain the effect of 'using' block in a bit more details.
http://www.codeproject.com/KB/cs/tinguusingstatement.aspx

Categories

Resources