Insert Sql function is not working - c#

I created a sale table which Insert function does not work properly. It shows the error message like this "ExecuteNonQuery requires an open and available Connection. The connection's current state is closed." If I removed Sql Close Statement on Line 14, it shows this error msg "There is already an open DataReader associated with this Command which must be closed first." My code below work like this. I checked available stocks from my Product table. If quantity order is greater than quantity from Product Table, show error message. Otherwise, proceed to inserting order information into Sale Table. Any help is appreciated.
private void btnOrder_Click(object sender, EventArgs e)
{
int iQuantityDB;
int iCustomerID = Convert.ToInt32(txtCustomerID.Text);
int iProductID = Convert.ToInt32(txtProductID.Text);
decimal dPrice = Convert.ToDecimal(txtPrice.Text);
int iQuantity = Convert.ToInt32(txtQuantity.Text);
decimal dSubtotal = Convert.ToDecimal(txtSubTotal.Text);
decimal dGST = Convert.ToDecimal(txtGST.Text);
decimal dTotal = Convert.ToDecimal(txtTotal.Text);
string strConnectionString = #"Data Source = KK\SQLEXPRESS; Integrated Security = SSPI; Initial Catalog = JeanDB; MultipleActiveResultSets=True;";
using (var sqlconn = new SqlConnection(strConnectionString))
{
sqlconn.Open();
string querySelectQuantity = #"Select Quantity from dbo.JeanProduct WHERE ProductID = #iProductID";
using (var cmdOrder = new SqlCommand(querySelectQuantity, sqlconn))
{
using (var sdRead = cmdOrder.ExecuteReader())
{
sdRead.Read();
iQuantityDB = Convert.ToInt32(sdRead["Quantity"]);
}
}
if (iQuantityDB > iQuantity)
{
string InsertQuery = #"INSERT INTO Sale(CustomerID, ProductID, Price, Quantity, Subtotal, GST, Total)VALUES(#iCustomerID, #iProductID, #dPrice, #iQuantity, #dSubtotal, #dGST, #Total)";
using (var InsertCMD = new SqlCommand(InsertQuery, sqlconn))
{
InsertCMD.Connection = sqlconn;
InsertCMD.Parameters.AddWithValue("#iCustomerID", iCustomerID);
InsertCMD.Parameters.AddWithValue("#iProdcutID", iProductID);
InsertCMD.Parameters.AddWithValue("#dPrice", dPrice);
InsertCMD.Parameters.AddWithValue("#iQuantity", iQuantity);
InsertCMD.Parameters.AddWithValue("#dSubtotal", dSubtotal);
InsertCMD.Parameters.AddWithValue("#dGST", dGST);
InsertCMD.Parameters.AddWithValue("#dTotal", dTotal);
InsertCMD.ExecuteNonQuery();
LoadDataonTable();
}
}
else
{
MessageBox.Show("no more stock");
}
sqlconn.Close();
}
}

You should change your connection string to
string strConnectionString = #"Data Source = KK\SQLEXPRESS;
Integrated Security = SSPI;
Initial Catalog = JeanDB;
MultipleActiveResultSets=True";
And do not close the connection between the Reader.Read and the ExecuteNonQuery.
You need at least Sql Server 2005 for this to work.
The connection used by a SqlDataReader cannot be used for other operations unless you set the connection string with the MultipleActiveResultSets key. Of course you could open two connection objects (with the same connection string) and use one for the SqlDataReader and one to Execute your command.
Not really linked to your problem, but I suggest to use a parameterized query also for the SELECT part of your code.
Moreover, you should use the Using Statement around the disposable object to ensure the proper closing and disposing also in case of exceptions. Finally, the syntax used in the INSERT INTO is not correct. I think that this code could explain some of the points explained above.
string strConnectionString = #"......;MultipleActiveResultSets=True;";
using(SqlConnection sqlconn = new SqlConnection(strConnectionString))
{
sqlconn.Open();
string querySelectQuantity = #"Select Quantity from dbo.JeanProduct
WHERE ProductID = #id";
using(SqlCommand cmdOrder = new SqlCommand(querySelectQuantity, sqlconn))
{
cmdOrder.AddWithValue("#id", Convert.ToInt32(txtProductID.Text));
using(SqlDataReader sdRead = cmdOrder.ExecuteReader())
{
if(sdRead.Read())
{
.....
string InsertQuery = #"INSERT INTO Sale(SaleID, CustomerID, ProductID,
Price, Quantity, Subtotal, GST, Total)VALUES(#iCustomerID,
#iProductID, #dPrice, #iQuantity,
#dSubtotal, #dGST, #Total)";
using(SqlCommand InsertCMD = new SqlCommand(InsertQuery, sqlconn))
{
InsertCMD.Parameters.AddWithValue("#iCustomerID", iCustomerID);
....
InsertCMD.ExecuteNonQuery();
LoadDataonTable();
}
}
else
{
MessageBox.Show("no more stock");
}
}
}
}

You've closed your SqlConnection after the reader execution / read cycle (and in the other error, you've kept the reader open while trying to execute another command).
Either close the reader and leave the connection open for the insert, or open a new connection for the insert.
Better still, use using to handle the disposal of the resources for you, and scope the DB resources to be released as soon as you are done with them, e.g.:
using (var sqlconn = new SqlConnection(strConnectionString))
{
sqlconn.Open();
string querySelectQuantity = "Select Quantity ...";
using var (cmdOrder = new SqlCommand(querySelectQuantity, sqlconn))
{
int iQuantityDB;
using (var sdRead = cmdOrder.ExecuteReader())
{
sdRead.Read();
iQuantityDB = Convert.ToInt32(sdRead["Quantity"]);
} // Dispose reader
// sqlconn.Close(); <-- Don't close
} // cmdOrder disposed here
if (iQuantityDB > iQuantity)
{
string InsertQuery = "INSERT INTO ...";
using var (InsertCMD = new SqlCommand(InsertQuery, sqlconn))
{
// ...
} // InsertCmd disposed here
}
} // Sql Connection disposed here
This will overcome many bugs, such as the one you've got where you are conditionally closing the command + connection in an if branch.

Related

extracting a fill method from a form

I have a combobox on a windows form that I fill with a list of names. At the moment I have the following code inside the Form class and it works fine
// This section opens a connection to the database, selects all the portfolio names that have an "in Use" value of 1, and then
// fills Combo Box 2 with the values.
SqlConnection myConnection = new SqlConnection(#"Data Source = (LocalDB)\MSSQLLocalDB; AttachDbFilename = ""C:\Users\Nick\Documents\Investments 4.mdf""; Integrated Security = True; Connect Timeout = 30");
myConnection.Open();
SqlCommand myCommand2 = new SqlCommand();
myCommand2.Connection = myConnection;
myCommand2.CommandText = "SELECT Portfolio_Name FROM Dbo.Name WHERE In_use = 1";
SqlDataReader myReader2 = myCommand2.ExecuteReader();
while (myReader2.Read())
{
comboBox2.Items.Add(myReader2[0]);
}
myConnection.Close();
I would like to be able to extract this into a separate method, and put it into a separate class for general utility methods. However, I'm stuck on a really simple issue. When I put the code into a class, I need to be able to tell it which combox box I want to fill, and I can't figure out how to pass in that information. Sorry if the answer is obvious, but any help would be gratefully received.
Thanks!
Well, if you want to extract, then extract:
// Let's extract a class: it should provide us standard cursors,
// e.g. Protfolio Names
public static class MyData {
// Let's enumerate items returned
public static IEnumerable<string> PortfolioNames() {
// Wrap IDisposable into using
//TODO: move Connection String into a separated method/property
using (SqlConnection con = new SqlConnection(/*connection string here*/)) {
con.Open();
// Make sql readable
//DONE: when presenting something to user, sort it (order by) esp. strings
string sql =
#" select Portfolio_Name
from Dbo.Name
where In_use = 1
order by Portfolio_Name";
// Wrap IDisposable into using
using (SqlCommand q = new SqlCommand(sql, con)) {
// Wrap IDisposable into using
using (var reader = q.ExecuteReader()) {
while (reader.Read())
yield return Convert.ToString(reader[0]);
}
}
}
}
}
And then use
// Adding items in one after one manner is often a bad idea:
// it makes UI repaint each time you add an item and cause blinking.
// Let's fill the ComboBox in one go via AddRange
comboBox2.Items.AddRange(MyData.PortfolioNames().ToArray());
You can use a helper class names Portfolio for data access. The method GetNames does not require a ComboBox instance. This increases the chance that you can reuse the method in another context.
public static class Portfolio
{
public static IList<string> GetNames()
{
SqlConnection myConnection = new SqlConnection(#"Data Source = (LocalDB)\MSSQLLocalDB; AttachDbFilename = ""C:\Users\Nick\Documents\Investments 4.mdf""; Integrated Security = True; Connect Timeout = 30");
myConnection.Open();
SqlCommand myCommand2 = new SqlCommand();
myCommand2.Connection = myConnection;
myCommand2.CommandText = "SELECT Portfolio_Name FROM Dbo.Name WHERE In_use = 1";
SqlDataReader myReader2 = myCommand2.ExecuteReader();
var portfolioNames = new List<string>();
while (myReader2.Read())
{
portfolioNames.Add(myReader2[0]);
}
myConnection.Close();
return portfolioNames;
}
}
Then in your Form you can do something like this:
var names = Portfolio.GetNames();
foreach (var name in names)
{
combobox2.Items.Add(name);
}
It is so simple:
public class MyUtility
{
public static void FillComboBox(System.Windows.Forms.ComboBox comboBox)
{
//comboBox.Items.Clear(); //enable this line if required
using (SqlConnection myConnection = new SqlConnection(#"Data Source = (LocalDB)\MSSQLLocalDB; AttachDbFilename = ""C:\Users\Nick\Documents\Investments 4.mdf""; Integrated Security = True; Connect Timeout = 30"))
{
myConnection.Open();
using (SqlCommand myCommand2 = new SqlCommand())
{
myCommand2.Connection = myConnection;
myCommand2.CommandText = "SELECT Portfolio_Name FROM Dbo.Name WHERE In_use = 1";
using (SqlDataReader myReader2 = myCommand2.ExecuteReader())
{
while (myReader2.Read())
{
comboBox.Items.Add(myReader2[0]);
}
}
}
//myConnection.Close(); //not required inside using block
}
}
}
you may use other methods to get connection string (e.g. from config file).
The usage is so simple, no extra code required:
MyUtility.FillComboBox(comboBox2);

SqlDataReader not reading any row apart from first

New to stackoverflow and very much a c# beginner
Currently creating a form which produces a bar chart from data stored in a database. The chosen record is identified by pID (patient's ID) and tdate (Test date). These values are determined by 2 combo boxes that the user can select from, The problem I am having is that only the first and last records stored in the database are populating the barchart.
if (radioButtonTestResult.Checked)
{
foreach (var series in TestResultBarChart.Series)
{
series.Points.Clear();
}
string tdate = comboBox2.Text;
using (SqlConnection connection = new SqlConnection(#"Data Source= (LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\MMSEDB.mdf;Integrated Security=True"))
{
connection.Open();
string sql = "SELECT T_CLOCK_SCORE,T_LANGUAGE_SCORE,T_RECALL_SCORE,T_REGISTRATION_SCORE,T_ORIENTATION _SCORE,T_TIME FROM TEST_RESULTS WHERE P_ID='" + pID + "' AND T_DATE='"+ tdate +"'";
using(SqlCommand command = new SqlCommand(sql, connection))
{
command.CommandTimeout = 3600;
using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess))
{
while (reader.Read())
{
MessageBox.Show("hello4");
String clockScoreString = reader["T_CLOCK_SCORE"].ToString();
MessageBox.Show(clockScoreString);
clockScore = Int32.Parse(clockScoreString);
String langScoreString = reader["T_LANGUAGE_SCORE"].ToString();
langScore = Int32.Parse(langScoreString);
String recallScoreString = reader["T_RECALL_SCORE"].ToString();
recallScore = Int32.Parse(recallScoreString);
String regScoreString = reader["T_REGISTRATION_SCORE"].ToString();
regScore = Int32.Parse(regScoreString);
String orientScoreString = reader["T_ORIENTATION_SCORE"].ToString();
orientScore = Int32.Parse(orientScoreString);
String timeScoreString = reader["T_TIME"].ToString();
timeScore = Int32.Parse(timeScoreString);
}
reader.Close();
}
}
this.TestResultBarChart.Series["Series1"].Points.AddXY("Clock Score", clockScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Language Score", langScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Recall Score", recallScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Registration Score", regScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Orientation Score", orientScore);
}
}
Here is a pic of the data:
Test_results_table
here is a pic of the interface with the first record working:
interface
I know this has something to do with the reader but can't work out how to get to function correctly
Any help is very much appreciated
You are reading in a loop all the returned values, then exit from the loop and use just the last value to set your Points. You should move the Point settings inside the loop
....
while (reader.Read())
{
clockScore = Convert.ToInt32(reader["T_CLOCK_SCORE"]);
langScore = Convert.ToInt32(reader["T_LANGUAGE_SCORE"]);
recallScore = Convert.ToInt32(reader["T_RECALL_SCORE"]);
regScore = Convert.ToInt32(reader["T_REGISTRATION_SCORE"]);
orientScore = Convert.ToInt32(reader["T_ORIENTATION_SCORE"]);
timeScore = Convert.ToInt32(reader["T_TIME"]);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Clock Score", clockScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Language Score", langScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Recall Score", recallScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Registration Score", regScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Orientation Score", orientScore);
}
reader.Close();
Note that your query is built using string concatenation. This is a well known problem with database code. Never do it and use a parameterized query
EDIT
Looking at your comment below, I repeat the advice to use a parameterized query instead of string concatenation. Not only this avoid Sql Injection hacks but also you don't leave the job to understand the meaning of your values to the database engine
DateTime tDate = Convert.ToDateTime(comboBox2.Text);
......
string sql = #"SELECT
T_CLOCK_SCORE,T_LANGUAGE_SCORE,T_RECALL_SCORE,
T_REGISTRATION_SCORE,T_ORIENTATION_SCORE,T_TIME
FROM TEST_RESULTS
WHERE P_ID=#id AND T_DATE=#date";
using(SqlCommand command = new SqlCommand(sql, connection))
{
command.Parameters.Add("#id", SqlDbType.Int).Value = pID;
command.Parameters.Add("#date", SqlDbType.Date).Value = tdate;
command.CommandTimeout = 3600;
using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess))
{
while (reader.Read())
....
In this example I assume that the variable pID is of type integer and the variable tDate is of type DateTime matching the type of the database fields. This doesn't leave any doubt to the database engine on your values.
Of course if the fields are of different type then you should change the SqlDbType accordingly.

Specifies that I have problems with my conn.open and my Conn.Close

this is how I select some content twice and when I get into the middle to select so like that it gives me trouble to select something on file.
The problem I have never seen before,
I think it's something with conn.open() and Conn.Close()
my code looks like this:
int prisId = Convert.ToInt32(Request.QueryString["Id"]);
cmd.Parameters.AddWithValue("#ppId", prisId);
cmd.CommandText = "SELECT priser FROM Priser WHERE Id = #ppId;";
conn.Open();
SqlDataReader readerPriser = cmd.ExecuteReader();
if (readerPriser.Read())
{
PanelerrorHandelsbetingelser.Visible = false;
string Brugerid = Session["id"].ToString();
cmd.Parameters.AddWithValue("#brugerid", Brugerid);
cmd.CommandText = "SELECT id, brugernavn, fornavn, efternavn FROM brugere WHERE Id = #brugerid;";
SqlDataReader readerBrugerid = cmd.ExecuteReader();
if (readerPriser.Read())
{
Session["id"] = readerBrugerid["id"].ToString();
Session["brugernavn"] = readerBrugerid["brugernavn"].ToString();
Session["fornavn"] = readerBrugerid["fornavn"].ToString();
Session["efternavn"] = readerBrugerid["efternavn"].ToString();
Session["adresse"] = TextBoxAdresse.Text;
Session["post"] = TextBoxPost.Text;
Session["telefon"] = TextBoxTelefon.Text;
Session["prisen"] = readerPriser["priser"].ToString();
LabelErrorBuyNow.Text = " - Yeaaa Jesper!";
}
else
{
LabelErrorBuyNow.Text = " - Der findes intet med dit brugerid!";
}
}
conn.Close();
problems come after line 9-10
The problem is such that it appears this one mistake on my part: There is already an open DataReader associated with this Command which must be closed first.
Always remember to release resources after they are used. So at the method end, you should:
cmd.Parameters.Clear();
readerPriser.Close();
conn.Close();
The exception tells you exactly what is wrong.
You have tried to run two SqlDataReaders over the same connection without either specifying MultipleActiveResultSets=True in your connection string or else first closing the first reader.
You have three options:
Use a second connection to run the second SqlDataReader.
Add "MultipleActiveResultSets=True" to your connection string.
Close the first SqlDataReader before using the second.
You need to close the readerPriser first be
readerPriser.Close();
Then affiliate the same command with next reader.
Always close the readers after using them.
There are two problems here. First of all, you are not placing all of your IDisposable objects into using blocks. Second, you are reusing the same SqlCommand for different queries. Third, your second Read call is using the wrong SqlDataReader.
Try
using (SqlConnection conn = new SqlConnection(...)){
conn.Open();
using (SqlCommand selectPriser = new SqlCommand("SELECT priser FROM Priser WHERE Id = #ppId;", conn))
{
selectPriser.Parameters.AddWithValue("#ppId", prisId);
using (SqlDataReader readerPriser = selectPriser.ExecuteReader())
{
if (readerPriser.Read())
{
// ...
using (SqlCommand selectBrugere = new SqlCommand("SELECT id, brugernavn, fornavn, efternavn FROM brugere WHERE Id = #brugerid;"){
string Brugerid = Session["id"].ToString();
selectBrugere.Parameters.AddWithValue("#brugerid", Brugerid);
using (SqlDataReader readerBrugerid = selectBrugere.ExecuteReader()){
if (readerBrugerid.Read()){
// ...
}
}
}
}
}
}
}

efficient way to apply operator on specific record in MsAccess Database

public void moveBooks(int quantityOfMovedBooks, int booksID)
{
int finalQuantityOfBooks = totalBooksInDB(booksID) - quantityOfMovedBooks;
queryString = "update Books set bQuantity='" + finalQuantityOfBooks + "'where bID=" + booksID;
myComm = new OleDbCommand(queryString, myConn);
myConn.Open();
myComm.ExecuteNonQuery();
myConn.Close();
}
public int totalBooksInDB(int bID)
{
int booksQuantity;
queryString = "select bQuantity from Books where bID=" + bID;
myComm = new OleDbCommand(queryString, myConn);
myConn.Open();
booksQuantity = (int)myComm.ExecuteScalar();
myConn.Close();
return booksQuantity;
}
im beginner in MSAccess Database and C#, im maintaing a Table in which there are 3 fields one is BookID, second is BookName, third is BookQuantity.. scope is when books are moved to aisle books should be subtracted from main inventory.. im using this approach.. but i wonder is there any better or efficient way of doing this..
thanx in advance
A couple of changes.
First, never use string concatenation to build sql command text. This leads to sql injection attacks. A very serious security problem
Second, your code for getting the number of books could result in a null value returned by ExecuteScalar and thus you will get an error
Third. The connection should be opened when needed, used, and then closed and disposed. Your code will fail to close and dispose the connection if, for whatever reason, you get an exception.
The using statement prevent this issue taking care to close and dispose of the connection also in case of exceptions.
Fourth well this is more a logical problem. I think that you can't move more books than those stored in the inventory, so add a check just to be safe-
public void moveBooks(int quantityOfMovedBooks, int booksID)
{
int quantity = totalBooksInDB(booksID);
if(quantity > quantityOfMovedBooks)
{
int finalQuantityOfBooks = quantity - quantityOfMovedBooks;
queryString = "update Books set bQuantity=? where bID=?";
using ( OleDbConnection myConn = new OleDbConnection(GetConnectionString() )
using ( OleDbCommand myComm = new OleDbCommand(queryString, myConn))
{
myComm.Parameters.AddWithValue("#p1", finalQuantityOfBooks);
myComm.Parameters.AddWithValue("#p2", booksID);
myConn.Open();
myComm.ExecuteNonQuery();
}
}
else
MessageBox.Show("Invalid quantity to move");
}
public int totalBooksInDB(int bID)
{
int booksQuantity = 0;
queryString = "select bQuantity from Books where bID=?";
using ( OleDbConnection myConn = new OleDbConnection(GetConnectionString() )
using ( OleDbCommand myComm = new OleDbCommand(queryString, myConn))
{
myComm = new OleDbCommand(queryString, myConn);
myComm.Parameters.AddWithValue("#p1", bID);
myConn.Open();
object result = myComm.ExecuteScalar();
if(result != null)
booksQuantity = Convert.ToInt32(result);
}
return booksQuantity;
}

Using Multiple Data Readers

I am developing a WinForm Application in C Sharp on the .net framework.
The database string I am using as of now is
<add key="Conn" value="Data Source=MNTCON016; Database=Overtime_Calculator;Trusted_Connection=True;MultipleActiveResultSets=true" />
As I am using Microsoft SQL Server 2005 for development, I can use 2 data readers simultaneously using the MultipleActiveResultSets property to true as mentioned above.
The Method used to invoke the 2 data readers is as follows:
public static void SignUpControllerDay(DateTime Date, System.Windows.Forms.DataGridView PassedGrid)
{
string sql_SignUp = String.Format(#"SELECT Emp_ID as Emp_ID, Name as Name, Sum(Sum) as Sum FROM
(SELECT DISTINCT o.Date, e.Emp_ID as Emp_ID,
e.First_Name+ ' ' +e.Last_Name as Name,
o.Quantity as Sum
FROM Employee e,OT_Hours o,Position p,Signup_Sheet s
WHERE e.Emp_ID=o.Emp_ID
and e.Emp_ID = s.Employee_ID
and s.Day_Shift = 1
and e.Position_ID = p.Position_ID
and p.Position_Name = 'Controller'
and o.Quantity NOT IN(0.3)
and s.Date = '{0}'
and o.Date <= CONVERT(VARCHAR,'{0}',101) AND o.Date > CONVERT(VARCHAR,DATEADD(YYYY,-1,'{0}'),101) )
as OVERTIME
GROUP BY Emp_ID,Name
ORDER BY Sum", Date);
SqlConnection sqlConn = null;
SqlCommand cmd_SignUp;
SqlDataReader dr_SignUp;
try
{
sqlConn = new SqlConnection(databaseConnectionString);
sqlConn.Open();
cmd_SignUp = new SqlCommand(sql_SignUp, sqlConn);
dr_SignUp = cmd_SignUp.ExecuteReader();
while (dr_SignUp.Read())
{
ArrayList arrPhone = new ArrayList();
string sql_Phone = String.Format("SELECT Phone_Number FROM Contact_Details WHERE Emp_ID = {0}", dr_SignUp["Emp_ID"]);
SqlCommand cmd_Phone = new SqlCommand(sql_Phone, sqlConn);
SqlDataReader dr_Phone = cmd_Phone.ExecuteReader();
while (dr_Phone.Read())
{
arrPhone.Add(dr_Phone["Phone_Number"].ToString());
}
//--Retrieving Sectors
ArrayList arrSector = new ArrayList();
string sql_Sector = String.Format(#"SELECT e1.EMP_ID,
( SELECT cast(Sector_ID as varchar(10)) + ';'
FROM Employee_Sector_relationship e2
WHERE e2.Emp_ID = e1.Emp_ID
ORDER BY Sector_ID
FOR XML PATH('') ) AS Sectors
FROM Employee_Sector_Relationship e1
WHERE Emp_ID = {0}
GROUP BY Emp_ID ", dr_SignUp["Emp_ID"]);
SqlCommand cmd_Sector = new SqlCommand(sql_Sector, sqlConn);
SqlDataReader dr_Sector = cmd_Sector.ExecuteReader();
while (dr_Sector.Read())
{
arrSector.Add(dr_Sector["Sectors"].ToString());
}
if (arrSector.Count == 0)
{ arrSector.Add(" "); }
if (arrPhone.Count == 0)
{ arrPhone.Add(" "); }
//--
if (arrPhone.Count == 2)
{
PassedGrid.Rows.Add(dr_SignUp["Emp_ID"].ToString(), dr_SignUp["Name"].ToString(), arrSector[0], dr_SignUp["Sum"], arrPhone[0], arrPhone[1]);
}
else
{
PassedGrid.Rows.Add(dr_SignUp["Emp_ID"].ToString(), dr_SignUp["Name"].ToString(), arrSector[0], dr_SignUp["Sum"], arrPhone[0]);
}
}
}
catch (Exception e)
{
MessageBox.Show("Error found in SignUpControllerDay..." + Environment.NewLine + e.ToString());
}
finally
{
if (sqlConn != null)
{
sqlConn.Close();
}
}
}
Everything works fine.
Now the real problem. I have been informed that the production SQL server for the application to go live is Microsoft SQL server 2000. After doing a bit research, I came to know that Microsoft server 2000 does not support multiple active results sets propery. In short, it does not allow me to use 2 data readers simultaneously.
I need to know how to read the data from 2 different tables, simultaneously, with regards to SQL Server 2000.
Are there any other ways that i can read data as I have mentioned in the code..
Please help..
the application is almost done and is ready to go to production. but MS server 2000 doesnt allow the applcaition to work accordingly...
please help
You can have two active datareaders in Sql Server 2000 by simply creating two connections.
To demonstrate this, I must first berate you for using two very poor practices: dynamic sql and arraylists. Neither have any place in your code. You should also read up on the using construct, though you have my apologies and condolences on "using" and "arraylists" if you're still using .net 1.1.
That said, here's how the code should look:
string sql_Phone = "SELECT Phone_Number FROM Contact_Details WHERE Emp_ID = #EmpID";
using (SqlConnection cn2 = new Sqlconnection(databaseConnectionString))
using (SqlCommand cmd_Phone = new SqlCommand(sql_Phone, cn2))
{
cmd_Phone.Parameters.Add("#EmpID", SqlDbType.Int);
cn2.Open();
while (dr_SignUp.Read())
{
List<string> arrPhone = new List<string>();
cmd_Phone.Parameters[0].Value = dr_SignUp["Emp_ID"];
using (SqlDataReader dr_Phone = cmd_Phone.ExecuteReader())
{
while (dr_Phone.Read())
{
arrPhone.Add(dr_Phone["Phone_Number"].ToString());
}
}
Also, looking at your code I suspect what you really need to do is re-write your sql. You can combine all those into a single query that you just bind directly to the grid.
Sure:
public void SignUpControllerDay()
{
using (var conn = new SqlConnection(ConnectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "SELECT ...";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var phone = reader["Phone_Number"].ToString();
Bar(phone);
}
}
}
}
public void Bar(string phone)
{
using (var conn = new SqlConnection(ConnectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "SELECT ..."; // use phone to prepare statement
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// Fill the grid
}
}
}
}
You could open multiple database connections with 1 reader per connection
You could also add MultipleActiveResultSets=True; to the connection string, even though it's not recommended.
so, it is not possible! as simple as that the only answer!
multiple connection is a workaroud!
one connection can not handle multiple recordsets simultaneously

Categories