I made function in c# to read line by line and then load lines to sqlite (s3db).
private void LoadFromDictionary()
{
Encoding enc = Encoding.GetEncoding(1250);
using (StreamReader r = new StreamReader("c:\\Temp2\\dictionary.txt", enc))
{
string line = "";
while ((line = r.ReadLine()) != null)
{
line = line.Trim();
AddWord(line);
}
}
MessageBox.Show("Finally :P", "Info");
}
private void AddWord(string w)
{
String insSQL = "insert into Words values(\"" + w + "\")";
String strConn = #"Data Source=C:\Temp2\dictionary.s3db";
SQLiteConnection conn = new SQLiteConnection(strConn);
SQLiteDataAdapter da = new SQLiteDataAdapter(insSQL, strConn);
da.Fill(dt);
dataGridView1.DataSource = dt.DefaultView;
}
But is it any faster way? I created table by sqlite administrator application.
Can sqlite load itself file and make it as a table?
I am talking about 3+ millions words (one word in one line).
PS. please correct my topic if there is something wrong :)
Yes, there is a much, much faster method using the following techniques:
1) Only open a connection to the database one time
2) Use a parameterized command for better performance and lower overhead (don't have to use new strings on each pass).
3) Wrap the entire operation in a transaction. As a general rule, this will improve your performance.
Note that I do not show transaction rollback or closing the connection, which are also best practices that should be implemented.
private void LoadFromDictionary()
{
Encoding enc = Encoding.GetEncoding(1250);
string strConn = #"Data Source=C:\Temp2\dictionary.s3db";
SqliteConnection conn = new SqliteConnection(strConn);
conn.Open();
string insSQL = "insert or ignore into wyrazy values(#Word)";
DbCommand oCommand = conn.CreateCommand();
oCommand.Connection = conn;
oCommand.CommandText = insSQL;
DbParameter oParameter = oCommand.CreateParameter();
oParameter.Name = "#Word";
oParameter.DbType = DbType.String;
oParameter.Size = 100;
oCommand.Parameters.Add(oParameter);
DbTransaction oTransaction = conn.BeginTransaction();
using (StreamReader r = new StreamReader("c:\\Temp2\\dictionary.txt", enc))
{
string line = "";
while ((line = r.ReadLine()) != null)
{
line = line.Trim();
if (!string.IsNullOrEmpty(line)) {
oParameter.Value = line;
oCommand.ExecuteNonQuery();
}
}
}
oTransaction.Commit();
conn.Close();
MessageBox.Show("Finally :P", "Info");
}
You could try bulk insert. By reading this article please pay special attention to the parametrized queries being used there and which you should use instead of the string concatenations in your sample in the insSQL variable.
Using Transactions usually speed things up quite a bit, depending on your desired batch size. I'm not 100% as familiar with DataAdapters and DataSources but instead of creating a new connection every time to insert one row, modify your code to use one connection and use SQLiteConnection.BeginTransaction() and the when you are done call Transaction.Commit().
I just did this the other day, first use a transaction, and parameterized queries. I was able to load 16 million rows in about a minute doing this.
internal static void FastInsertMany(DbConnection cnn)
{
using (DbTransaction dbTrans = cnn.BeginTransaction())
{
using (DbCommand cmd = cnn.CreateCommand())
{
cmd.CommandText = "INSERT INTO TestCase(MyValue) VALUES(?)";
DbParameter Field1 = cmd.CreateParameter();
cmd.Parameters.Add(Field1);
for (int n = 0; n < 100000; n++)
{
Field1.Value = n + 100000;
cmd.ExecuteNonQuery();
}
}
dbTrans.Commit();
}
}
Related
I wonder how can i bulk insert instead of execute this method everytime.
It's getting slow when i try to insert 1000 rows:
queryText = "INSERT INTO `player_items` (`player_id`, `item_id`, `count`) VALUES (#player_id, #item_id, #count)";
for (int i = 0; i < player.invenotrySize; i++)
{
Item item = player.inventory.GetItem[i];
MySqlParameter[] parameters = {
new MySqlParameter("player_id", 1),
new MySqlParameter("item_id", item.data.id),
new MySqlParameter("count", item.amount),
};
ExecuteNonQuery(queryText, parameters);
}
public int ExecuteNonQuery(string queryText, params MySqlParameter[] parameters)
{
int affectedRows = 0;
using (MySqlConnection mySqlConnection = CreateConnection())
{
using (MySqlCommand mySqlCommand = new MySqlCommand(queryText, mySqlConnection))
{
mySqlCommand.CommandType = CommandType.Text;
mySqlCommand.Parameters.AddRange(parameters);
affectedRows = mySqlCommand.ExecuteNonQuery();
}
}
return affectedRows;
}
I think the optimal way is to insert everything as a huge row. E.g
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
But i have no idea how i can make a method to take care of this setup
You are opening and closing your connection for every single insert.
using (MySqlConnection mySqlConnection = CreateConnection())
This is a very expensive procedure, and therefore not really the way to work with a DB.
You should open your connection just once, and then close it when finished. Depending on what you app does this might be when you start your App (or before you do your first DB query) and then close it when exiting the App (or after you are certain there will be no more DB queries.
Then ideally you should also reuse the SqlCommand instance as well. But you need to make sure that you clear your parameters in between. So then you have something like this
int affectedRows = 0;
using (MySqlConnection mySqlConnection = CreateConnection())
{
string queryText = "INSERT INTO `player_items` (`player_id`, `item_id`, `count`) VALUES (#player_id, #item_id, #count)";
using (MySqlCommand mySqlCommand = new MySqlCommand(queryText, mySqlConnection))
{
mySqlCommand.CommandType = CommandType.Text;
for (int i = 0; i < player.invenotrySize; i++)
{
Item item = player.inventory.GetItem[i];
MySqlParameter[] parameters = {
new MySqlParameter("player_id", 1),
new MySqlParameter("item_id", item.data.id),
new MySqlParameter("count", item.amount)};
mySqlCommand.Parameters.Clear();
mySqlCommand.Parameters.AddRange(parameters);
affectedRows += mySqlCommand.ExecuteNonQuery();
}
}
}
It's not realy clean with your "ExecuteNonQuery" (do a multi row insert solution or just isolate/singleton the connection class like the solution above, will be better) but you can construct your whole query before execute instead of get/add connection, replace, execute foreach player.
queryText = "INSERT INTO `player_items` (`player_id`, `item_id`, `count`) VALUES";
for (int i = 0; i < player.invenotrySize; i++)
{
Item item = player.inventory.GetItem[i];
MySqlParameter[] parameters = {
new MySqlParameter("player_id_"+i, 1),
new MySqlParameter("item_id_"+i, item.data.id),
new MySqlParameter("count_"+i, item.amount),
};
queryText+= " (#player_id_"+i+", #item_id_"+i+", #count_"+i+"),";
}
//remove the last ,
queryText= queryText.Remove(queryText.Length - 1)+";";
ExecuteNonQuery(queryText, parameters);
Altnernate for to skip params if you are sure about your data.
Item item = player.inventory.GetItem[i];
queryText+= " (1, "+item.data.id+", "+item.amount+"),";
I created an list named 'PTNList', and everything I needed added to it just fine. Now I am attempting to write code to retrieve each element from that list and run it against an SQL query. I have a feeling I'm not sure exactly how to about this. The CompareNumbers.txt file generates, but nothing is printed to it. Any help is greatly appreciated.
Below is the section of code I believe needs to be worked with.
using (FileStream fs = new FileStream("c:/temp/CompareNumbers.txt", FileMode.Append, FileAccess.Write))
using (StreamWriter sw = new StreamWriter(fs))
foreach (var ptn in PTNList)
{
//create sql for getting the count using "ptn" as the variable thats changing
//call DB with sql
//Get count from query, write it out to a file;
Console.WriteLine("Running Query");
string query2 = #"SELECT COUNT(PRODUCT_TYPE_NO)
AS NumberOfProducts
FROM dbo.PRODUCT
Where PRODUCT_TYPE_NO = " + ptn;
SqlCommand cmd2 = new SqlCommand(query2);
cmd2.Connection = con;
rdr = cmd2.ExecuteReader();
while (rdr.Read())
{
sw.WriteLine(rdr["NumberOfProducts"]);
}
rdr.Close();
}
You haven't used apostrophes around the values. But you should use parameters anyway. You could use one query instead of one for every type. For example with this approach:
string sql = #"SELECT COUNT(PRODUCT_TYPE_NO) AS NumberOfProducts
FROM dbo.PRODUCT
Where PRODUCT_TYPE_NO IN ({0});";
string[] paramNames = PTNList.Select(
(s, i) => "#type" + i.ToString()
).ToArray();
string inClause = string.Join(",", paramNames);
using (SqlCommand cmd = new SqlCommand(string.Format(sql, inClause)))
{
for (int i = 0; i < paramNames.Length; i++)
{
cmd.Parameters.AddWithValue(paramNames[i], PTNList[i]);
}
// con.Open(); // if not already open
int numberOfProducts = (int) cmd.ExecuteScalar();
}
Update: maybe you really just want to loop them and get their count. Then you don't need this complex approach. But you should still use sql-parameters to prevent sql-injection and other issues like missing apostrophes etc.
You'll want to convert the column back to a type, e.g.
sw.WriteLine(rdr["NumberOfProducts"] as string);
Also, note that your query is prone to SqlInjection attacks and should be parameterized, and that SqlCommand is also disposable. You can squeeze a bit more performance by reusing the SqlCommand:
string query2 = #"SELECT COUNT(PRODUCT_TYPE_NO)
AS NumberOfProducts
FROM dbo.PRODUCT
Where PRODUCT_TYPE_NO = #ptn";
using (var cmd2 = new SqlCommand(query2))
{
cmd2.Connection = con;
cmd2.Parameters.Add("#ptn", SqlDbType.Varchar);
foreach (var ptn in PTNList)
{
cmd2.Parameters["#ptn"].Value = ptn;
Console.WriteLine("Running Query");
using var (rdr = cmd2.ExecuteReader())
{
if (rdr.Read())
{
sw.WriteLine(rdr["NumberOfProducts"] as string);
}
}
}
}
Are you sure your query give an result and sw.WriteLine is executed? I would redesign your code like this, becfause if you have an error in your data query, you might get into trouble. I always like to use this (schema):
IDataReader reader = null;
try
{
// create every thing...
}
catch(Exception ex)
{
// catch all exceptions
}
finally()
{
if(reader != null)
{
reader.Close();
}
}
And use the same for your connection, so that you can be sure, it is closed correct.
I am working on a way to be able to run a SELECT Statement that returns more than one value into two different labels on my application.
The idea is to be able to get some version information from the database by running a select on the DB picked, I got the code to work but I know it's super sloppy and im just not really sure how to clean it up. I know there has to be a better way than what I have going on here.
// Update Version & Version2
string sqlCom1 = String.Format(#"SELECT [Version]
FROM ConfigSystem");
string sqlCom = String.Format(#"SELECT Version2
FROM ConfigSystem");
SqlConnectionStringBuilder ConnectionString = new SqlConnectionStringBuilder();
ConnectionString.DataSource = "SQL06";
ConnectionString.InitialCatalog = "SuperSweetDB";
ConnectionString.IntegratedSecurity = true;
SqlConnection cnn;
cnn = new SqlConnection(ConnectionString.ToString());
using (var version = new SqlCommand(sqlCom1, cnn))
{
cnn.Open();
label.Text = (string)version.ExecuteScalar();
cnn.Close();
};
using (var version = new SqlCommand(sqlCom, cnn))
{
cnn.Open();
label2.Text = (string)version.ExecuteScalar();
};
I think, and I'm not certain, that I am opening to connections to get data that I could easily get in SQL with one. The issue that it returns to columns worth of data and I have not been able to find it in Google on how to handle this. (I'm probably looking for the wrong thing)
I only did it this way because I really needed it to work, now I'm trying to clean everything up.
Just a heads up, Fairly new to C# or anything that is not SQL.
Any help is appreciated, if this is a duplicate question I apologize.
You can separate your 2 SQL statements with a semi-colon in 1 string variable, and then use the NextResult() method on the SqlDataReader to get multiple resultsets back.
I updated your code to work. See below. Notice the use of using keyword automatically disposes off the resources after code execution. I tested the code using SQL Server built in variables in 2 sql statements, which are commented.
You should be able to paste the following code in a console app and run it successfully.
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
namespace SqlMultipleResultsets
{
class Program
{
static void Main(string[] args)
{
SqlConnectionStringBuilder ConnectionString = new SqlConnectionStringBuilder();
ConnectionString.DataSource = "SQL06";
ConnectionString.InitialCatalog = "SuperSweetDB";
//ConnectionString.DataSource = "(localdb)\\Projects";
//ConnectionString.InitialCatalog = "tempdb";
ConnectionString.IntegratedSecurity = true;
string sqlSelect = #"SELECT [Version] FROM ConfigSystem;" +
#"SELECT Version2 FROM ConfigSystem";
// string sqlSelect = #"SELECT [Version] = ##VERSION;"
// + #"SELECT Version2 = ##LANGUAGE;" ;
int recordCount;
using (SqlConnection cnn = new SqlConnection(ConnectionString.ToString()))
{
using (SqlCommand command = new SqlCommand(sqlSelect, cnn))
{
cnn.Open( );
SqlDataReader dr = command.ExecuteReader( );
recordCount = 0;
do
{
Console.WriteLine("Result set: {0}", ++recordCount);
while (dr.Read( ))
{
Console.WriteLine("Version: {0}", dr[0]);
}
Console.WriteLine(Environment.NewLine);
}
while (dr.NextResult( ));
} // END command
} // END connection
Console.Write("Press a key to exit...");
Console.ReadKey();
} // END Main
}
}
You could create the SqlCommand only once and reuse it - you can set the command dynamically:
using (var version = new SqlCommand())
{
version.CommandType = CommandType.Text;
version.Connection = cnn;
cnn.Open();
version.CommandText = sqlCom1;
label.Text = (string)version.ExecuteScalar();
version.CommandText = sqlCom2;
label2.Text = (string)version.ExecuteScalar();
cnn.Close();
};
There are a lot of examples in the official SqlCommand class documentation at MSDN.
Here is the answer that I came up with in case anyone needs help on this in the future:
string sqlCom = String.Format(#"SELECT [Version],version2 FROM ConfigSystem");
SqlConnectionStringBuilder ConnectionString = new SqlConnectionStringBuilder();
ConnectionString.DataSource = SQL06;
ConnectionString.InitialCatalog = "SuperSweetdb";
ConnectionString.IntegratedSecurity = true;
SqlConnection cnn = new SqlConnection(ConnectionString.ToString());
using (var version = new SqlCommand(sqlCom, cnn))
{
cnn.Open();
using(IDataReader dataReader = version.ExecuteReader())
{
while (dataReader.Read())
{
label7.Text = dataReader["Version"].ToString();
label9.Text = dataReader["VertexDataVersion"].ToString();
}
}
};
What I ended up doing was breaking it down with datareader. This was kind of difficult to figure out and required a lot of tinkering but in the end it's a cleaner connection that prior to what I had.
Basically DataReader is what I was looking for.
Here is a link to something that helped out quite e bit: Invalid attempt to read when no data is present
As well as this: Multiple SQL queries asp.net c#
Hopefully anyone who has a similar problem will be able to get some help from this.
I am trying to display a column from my local database into a dropdown list. The problem is that I would need to split the data so that they are not displayed all in one line. I have used the ";" to separate the data and then using the split(";") method to split them. I have tried the code that I've wrote below but it's not working. Any help will be appreciated.
public string DisplayTopicNames()
{
string topicNames = "";
// declare the connection string
string database = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|/Forum.accdb;Persist Security Info=True";
// Initialise the connection
OleDbConnection myConn = new OleDbConnection(database);
//Query
string queryStr = "SELECT TopicName FROM Topics";
// Create a command object
OleDbCommand myCommand = new OleDbCommand(queryStr, myConn);
// Open the connection
myCommand.Connection.Open();
// Execute the command
OleDbDataReader myDataReader = myCommand.ExecuteReader();
// Extract the results
while (myDataReader.Read())
{
for (int i = 0; i < myDataReader.FieldCount; i++)
topicNames += myDataReader.GetValue(i) + " ";
topicNames += ";";
}
//Because the topicNames are seperated by a semicolon, I would have to split it using the split()
string[] splittedTopicNames = topicNames.Split(';');
// close the connection
myCommand.Connection.Close();
return Convert.ToString(splittedTopicNames);
}
You are returning just one column from the table.
There is no reason to use a for loop over a field count (it is always 1)
Instead you could use a List(Of String) to save the values returned by the rows found.
Then return this list to use as datasource for your DropDownList
List<string> topicNames = new List<string>();
// Extract the results
while (myDataReader.Read())
{
topicNames.Add(myDataReader.GetValue(0).ToString();
}
....
return topicNames;
However it is not clear if the field TopicName contains itself strings separated by semicolon.
In this case you could write:
List<string> topicNames = new List<string>();
// Extract the results
while (myDataReader.Read())
{
string[] topics = myDataReader.GetValue(0).ToString().Split(';')
topicNames.AddRange(topics);
}
...
return topicNames;
if you prefer to return an array of strings then it is just a matter to convert the list to an array
return topicNames.ToArray();
EDIT
Of course returning an array or a List(Of String) requires changes to the return value of your method
public List<string> DisplayTopicNames()
{
......
}
or
public string[] DisplayTopicNames()
{
......
}
if you still prefer to return a string separated by semicolons then change the return statement in this way
return string.Join(";", topicNames.ToArra());
Unless I've lost my mind, something like this should work:
while (myDataReader.Read())
{
for (int i = 0; i < myDataReader.FieldCount; i++)
ddl.Items.Add(myDataReader.GetValue(i))
}
where ddl is the name of your DropDownList. If your ddl isn't available here, then add them to a List<string> collection instead and return that. And then this code may now become irrelevant:
//Because the topicNames are seperated by a semicolon, I would have to split it using the split()
string[] splittedTopicNames = topicNames.Split(';');
// close the connection
myCommand.Connection.Close();
return Convert.ToString(splittedTopicNames);
but, on top of all this I want to restructure the code for you a little because you need to be leveraging things like using.
public string DisplayTopicNames()
{
string topicNames = "";
// declare the connection string
string database = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|/Forum.accdb;Persist Security Info=True";
// Initialise the connection
using (OleDbConnection myConn = new OleDbConnection(database))
{
myConn.Open();
// Create a command object
OleDbCommand myCommand = new OleDbCommand("SELECT TopicName FROM Topics", myConn);
// Execute the command
using (OleDbDataReader myDataReader = myCommand.ExecuteReader())
{
// Extract the results
while (myDataReader.Read())
{
for (int i = 0; i < myDataReader.FieldCount; i++)
{
ddl.Items.Add(myDataReader.GetValue(i));
}
}
}
}
// not sure anything needs returned here anymore
// but you'll have to evaluate that
return "";
}
The reason you want to leverage the using statement is to ensure that unmanaged resources that exist in the DataReader and Connection get disposed properly. When leaving the using statement it will automatically call Dispose on the object. This statement is only used for objects that implement IDisposable.
I think this should work:
public List<string> DisplayTopicNames()
{
List<string> topics = new List<string>();
// Initialise the connection
OleDbConnection conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|/Forum.accdb;Persist Security Info=True");
OleDbCommand cmd = new OleDbCommand("SELECT TopicName FROM Topics");
using(conn)
using(cmd)
{
cmd.Connection.Open();
// Execute the command
using(OleDbDataReader myDataReader = cmd.ExecuteReader())
{
// Extract the results
while(myDataReader.Read())
{
topics.Add(myDataReader.GetValue(0).ToString());
}
}
}
return topics;
}
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