c# Mysql There is already an open DataReader associated with this Connection - c#

Hello guys I am trying to do some stuff while reading. What I am trying to do is edit row which was just read. But I get error. Maybe u have some suggestions how should I fix it, to make it work without quitting the data reader. P.S: Ignore that, that queries are open for SQL injections .
string select = "Select * FROM ivykiai WHERE `Ivikio diena` MOD Periodiskumas_d = 0 AND `Ivikio diena` > 0 AND `Ivikio diena` < `Dif dien`";
MySqlCommand command = new MySqlCommand(select, cnn);
MySqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
db1 = (now - Convert.ToDateTime(reader["Nuo"])).TotalDays;
MessageBox.Show(db1.ToString());
db1 = db1 - Convert.ToInt32(reader["Ivikio diena"]);
MessageBox.Show(db1.ToString());
b = Convert.ToInt32(db1) / Convert.ToInt32(reader["Periodiskumas_d"]);
MessageBox.Show(b.ToString());
a =+ Convert.ToInt32(reader["Suma"]);
MessageBox.Show(a.ToString());
a = a * b;
MessageBox.Show(a.ToString());
string prideti = "Update Lesos Set Grynieji=Grynieji + '"+ a +"'";
MySqlCommand prideti_cmd = new MySqlCommand(prideti, cnn);
string p = prideti_cmd.ExecuteNonQuery().ToString();
string update = "UPDATE Ivikiai Set `Ivykio diena`+= '" + db1 + "'";
MySqlCommand update_cmd = new MySqlCommand(update, cnn);
string u = update_cmd.ExecuteNonQuery().ToString();
}
reader.Close();
cnn.Close();

You can't execute prideti_cmd and update_cmd using the same connection inside the while (reader.Read()) block and reader is still open, however you can do that outside the while (reader.Read()) block and after closing reader. I would suggest creating the following class
public class MyClass
{
public DateTime Nuo { get; set; }
public int IvikioDiena { get; set; }
public int Periodiskumas_d { get; set; }
public int Suma { get; set; }
}
and change your code as below
string select = "Select * FROM ivykiai WHERE `Ivikio diena` MOD Periodiskumas_d = 0 AND `Ivikio diena` > 0 AND `Ivikio diena` < `Dif dien`";
using (MySqlCommand command = new MySqlCommand(select, cnn))
{
// execute the select query and store the results to list variable
List<MyClass> list = new List<MyClass>();
using (MySqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
MyClass record = new MyClass();
record.Nuo = Convert.ToDateTime(reader["Nuo"]);
record.IvikioDiena = Convert.ToInt32(reader["Ivikio diena"]);
record.Periodiskumas_d = Convert.ToInt32(reader["Periodiskumas_d"]);
record.Suma = Convert.ToInt32(reader["Suma"]);
list.Add(record);
}
}
// enumerate list and execute both the update queries
foreach (var record in list)
{
db1 = (now - record.Nuo).TotalDays;
MessageBox.Show(db1.ToString());
db1 = db1 - record.IvikioDiena;
MessageBox.Show(db1.ToString());
b = Convert.ToInt32(db1) / record.Periodiskumas_d;
MessageBox.Show(b.ToString());
a =+ record.Suma;
MessageBox.Show(a.ToString());
a = a * b;
MessageBox.Show(a.ToString());
string prideti = "Update Lesos Set Grynieji=Grynieji + '"+ a +"'";
MySqlCommand prideti_cmd = new MySqlCommand(prideti, cnn);
string p = prideti_cmd.ExecuteNonQuery().ToString();
string update = "UPDATE Ivikiai Set `Ivykio diena`+= '" + db1 + "'";
MySqlCommand update_cmd = new MySqlCommand(update, cnn);
string u = update_cmd.ExecuteNonQuery().ToString();
}
}

Generally you can ever only have one active command - SQL Server MARS being a little exceptiohn.
So, you can not use a connection WHILE IT HAS AN OPEN READER. Your first need to finish reading, then can update- or use anothe connection, which will get you into transaction isolation troubles.

Try this:
using (MySqlConnection cnn = new MySqlConnection(dbConnectionString))
{
cnn.Open();
MySqlCommand command = new MySqlCommand(select, cnn);
using (MySqlDataReader reader = command.ExecuteReader())
{
db1 = (now - Convert.ToDateTime(reader["Nuo"])).TotalDays;
MessageBox.Show(db1.ToString());
db1 = db1 - Convert.ToInt32(reader["Ivikio diena"]);
MessageBox.Show(db1.ToString());
b = Convert.ToInt32(db1) / Convert.ToInt32(reader["Periodiskumas_d"]);
MessageBox.Show(b.ToString());
a = +Convert.ToInt32(reader["Suma"]);
MessageBox.Show(a.ToString());
a = a * b;
MessageBox.Show(a.ToString());
}
string prideti = "Update Lesos Set Grynieji=Grynieji + '" + a + "'";
MySqlCommand prideti_cmd = new MySqlCommand(prideti, cnn);
string p = prideti_cmd.ExecuteNonQuery().ToString();
string update = "UPDATE Ivikiai Set `Ivykio diena`+= '" + db1 + "'";
MySqlCommand update_cmd = new MySqlCommand(update, cnn);
string u = update_cmd.ExecuteNonQuery().ToString();
}
All of the variables needed for the ExecuteNonQuery() are set when the data is read so you can use them outside the MySqlDataReader.ExecuteReader() function.

Related

c# Using Two MysqlReaders

I want to retrive data from two differentables in my mysql data base so i created one connection and two readers, The second reader is not returning any results but the first reader is.
public List<BlogContentItemClass> BCITLIST = new List<BlogContentItemClass>();
// GET: api/BlogContents
[HttpGet]
public List<BlogContentItemClass> Get(string id)
{
string sqlstring = "server=; port= ; user id =;Password=;Database=;";
MySqlConnection conn = new MySqlConnection(sqlstring);
try
{
conn.Open();
}
catch (MySqlException ex)
{
throw ex;
}
string Query = "SELECT * FROM test.blogtable where `id` = '" + id + "' ";
MySqlCommand cmd = new MySqlCommand(Query, conn);
MySqlDataReader MSQLRD = cmd.ExecuteReader();
BlogContentItemClass BCIT = new BlogContentItemClass();
Label BLOGID = new Label();
if (MSQLRD.HasRows)
{
while (MSQLRD.Read())
{
string TC = (MSQLRD["Topic"].ToString());
string CT = (MSQLRD["Category"].ToString());
string SM = (MSQLRD["Summary"].ToString());
string BID = (MSQLRD["id"].ToString());
BCIT.TopicSaved1 = TC;
BCIT.CategoriesSaved1 = CT;
BCIT.SummarySaved1 = SM;
BLOGID.Text = BID;
BCIT.TotalBodyStackLayout1.Add("Hello");
}
}
BCITLIST.Add(BCIT);
MSQLRD.Close();
string Query1 = "SELECT * FROM test.blogbodytable where `BlogID` = '" + BLOGID.Text + "' ";
MySqlCommand cmd1 = new MySqlCommand(Query1, conn);
MySqlDataReader MSQLRD1 = cmd1.ExecuteReader();
if (MSQLRD1.HasRows)
{
while (MSQLRD1.Read())
{
string BLOGBODY ;
BLOGBODY = (MSQLRD1["BlogBody"].ToString());
BCIT.TotalBodyStackLayout1.Add(BLOGBODY);
}
}
BCITLIST.Add(BCIT);
conn.Close();
return BCITLIST;
}
from my code the line BCIT.TotalBodyStackLayout1.Add("Hello"); in the first reader does add "hello" to the BCIT.TotalBodyStacklayout1, but the line BCIT.TotalBodyStackLayout1.Add( BLOGBODY); does not work, what am i doing wrong?
Can you be more specific what you mean by 'BCIT.TotalBodyStackLayout1.Add(BLOGBODY);' does not work. Are you getting any exception? or if BLOGBODY coming empty? There are few primitive troubleshooting steps you can perform to nail-down the issue
confirm what BLOGID.Text you are getting from your previous query and corresponding data is available in test.blogbodytable for that id.
if (MSQLRD1.HasRows) is resolving to true
Were you able to get inside while (MSQLRD1.Read())

how to create an id to be shown in the text box based on selected dropdownlist

i would like to create an id generator based on their department selected from the dropdownlist. lets say my ddl has 3 departments (A,B,C) and when generating an id it will be A20181001 and then A20181002 upon submission but when i pick B from the ddl after sending A20181001 to the database, it will be B20181001.
so far i have created the code for the increment for the id without the departments. here is the code i did so far. (I used the date for today so the 20181001 is just an example):
void getMRF_No()
{
string year = DateTime.Now.Date.ToString("yyyyMMdd");
int mrf = 0;
int i;
string a;
//string x = Request.QueryString["BUnit"];
string mrfNo = "";
database db = new database();
string conn = dbe.BU();
SqlConnection connUser = new SqlConnection(conn);
SqlCommand cmd = connUser.CreateCommand();
SqlDataReader sdr = null;
string query = "SELECT TOP 1 MRF_NO FROM incMRF ORDER BY MRF_NO DESC";
connUser.Open();
cmd.CommandText = query;
sdr = cmd.ExecuteReader();
while (sdr.Read())
{
mrfNo = sdr.GetInt32(0).ToString();
}
if (mrfNo == "")
{
mrfNo = Convert.ToString(year) + "" + 00;
}
mrf += 0;
i = Convert.ToInt32(mrfNo) + 1;
a = i.ToString();
txtMRFNo.Text = a;
connUser.Close();
}
any help to improve this code will be helpful. thank you :)
EDIT:
here is the dropdown list code:
void SelectBU()
{
string database = dbe.BU ();
using (SqlConnection con = new SqlConnection(database))
{
con.Open();
string query = "select BUnit from BusinessUnit";
using (SqlDataAdapter sda = new SqlDataAdapter(query, con))
{
DataSet ds = new DataSet();
sda.Fill(ds, "BUnit");
ddlBu.DataSource = ds;
ddlBu.DataTextField = "BUnit";
ddlBu.DataValueField = "BUnit";
ddlBu.DataBind();
selectOption(ddlBu, "Select Dept");
}
con.Close();
}
}
EDIT2: I will state what im searching for here incase some doesnt know or understand. What i want is upon selecting a department from a dropdownlist, for example i picked A. the textbox show show A2018102201. if i select B it should show B2018102201 and if its C then c2018102201. and it will change its number once i submit it to a database and a new form loads. So if A2018102201 is already in the database, then the text shown in the text box will be A2018102202. BUT if i select B then the textbox will show B2018102201 since it does not exist in the database yet.
First you should get max ID, then increase the numeric part of your Id, and If this is a multi-user application, you have to lock your table, because it might create many ID duplication, Therefore I'm not recommend to create ID like this on c#, it is better to create a Sequence on SQL server. but I wrote this sample for you, just call it with proper value.
static string getMRF_No(string prefixCharFromDropDownList)
{
string year = DateTime.Now.Date.ToString("yyyyMMdd");
string mrfNo = "";
SqlConnection connUser = new SqlConnection("Server=130.185.76.162;Database=StackOverflow;UID=sa;PWD=$1#mssqlICW;connect timeout=10000");
SqlCommand cmd = new SqlCommand(
$"SELECT MAX(MRF_NO) as MaxID FROM incMRF where MRF_NO like '{prefixCharFromDropDownList}%'"
,connUser
);
connUser.Open();
SqlDataReader sdr = cmd.ExecuteReader();
while (sdr.Read())
{
mrfNo = sdr["MaxID"].ToString();
}
if (mrfNo == "")
{
mrfNo = prefixCharFromDropDownList + year + "000";
}
else
{
mrfNo = prefixCharFromDropDownList + (long.Parse(mrfNo.Substring(1)) + 1).ToString().PadLeft(2);
}
sdr.Close();
cmd = new SqlCommand($"INSERT INTO incMRF (MRF_NO) values ('{mrfNo}')",connUser);
cmd.ExecuteNonQuery();
connUser.Close();
//txtMRFNo.Text = prefixCharFromDropDownList + i.ToString();
return mrfNo;
}
I call this method on a console application as test.
static void Main(string[] args)
{
// send dropdown (selected char) as prefix to method
var newAId = getMRF_No("A");
var newAnotherAId = getMRF_No("A");
var newBId = getMRF_No("B");
var newAnotherAId2 = getMRF_No("A");
Console.ReadKey();
}

SQL update command in c#

I have a SQL Server table with columns like this:
Mobile No <> OTP <> GenTime <> AuthTime <> IsAuth
9632587410 <> 256389 <> ****** <> ******** <> False
9876543210 <> 258963 <> ***** <> ****** <> False
so on ...
using (SqlConnection conn = new SqlConnection())
{
string inputn = Console.ReadLine();
long mobileNo;
long.TryParse(inputn, out mobileNo);
string inputo = Console.ReadLine();
int OTP;
Int32.TryParse(inputo, out OTP);
DateTime now = DateTime.Now;
conn.ConnectionString = "Data Source=10.0.0.98;Initial Catalog=TeletextCMS_Dev;User ID=Testteam;Password=Cognigent33#";
conn.Open();
//long r = 8947052876;
SqlCommand command = new SqlCommand("SELECT * FROM CustomerAuthOTP WHERE MobileNum=" + mobileNo, conn);
int f = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
//int OTP = reader[1];
int OTPGen = int.Parse(string.Format("{0}", reader[1]));
int a = now.Hour;
int b = now.Minute;
int e = now.Day;
DateTime then = DateTime.Parse(string.Format("{0}", reader[2]));
int c = then.Hour;
int d = then.Minute;
int g = then.Day;
if (e == g)
{
int t = (a - c) * 60 + b - d;
if (OTP == OTPGen && e == g && t <= 15)
{
Console.WriteLine("Hi");
f = 1;
}
else
{
Console.WriteLine("No");
}
}
if (e > g)
{
int t = (a + 24 - c) * 60 + b - d;
if (OTP == OTPGen && e == g && t <= 15)
{
Console.WriteLine("Hi");
f = 1;
}
else
{
Console.WriteLine("No");
}
}
}
}
if(f == 1)
{
SqlCommand cmd = new SqlCommand("UPDATE CustomerAuthOTP SET IsAuthenticated=True, AuthenticationTime=" + now, conn);
Console.WriteLine("Hi");
}
}
Now at the bottom I have an Update command. I tried to execute it but it is not doing anything.
There is no error in the code. Kindly some one help me out if f== 1 then in the CustomerAuthOTP table update the IsAuthenticated value to be true and also set the authentication time to now.DateTime()
First of all you should execute your commnd:
SqlCommand cmd = new SqlCommand("UPDATE CustomerAuthOTP SET IsAuthenticated=True, AuthenticationTime=" + now, conn);
cmd.ExecuteNonQuery();
I recommend to use SqlCommand.Parameters
var commandText = "UPDATE CustomerAuthOTP SET IsAuthenticated=#IsAuthenticated, AuthenticationTime=#AuthenticationTime";
SqlCommand cmd = new SqlCommand(commandText, conn);
cmd.Parameters.AddWithValue("#IsAuthenticated", true);
cmd.Parameters.AddWithValue("#AuthenticationTime", now);
cmd.ExecuteNonQuery();
It'll help SQL provider to determine parameter types and protects against SQL-injections.
DateTime now = DateTime.Now;
...
SqlCommand cmd = new SqlCommand(
"UPDATE CustomerAuthOTP SET IsAuthenticated=True, AuthenticationTime="
+ now, conn);
Note that this will be a string concatenation, and (depending on your locale, etc), the following is not valid TSQL:
UPDATE CustomerAuthOTP SET IsAuthenticated=True, AuthenticationTime=08/12/2015 12:08:32
The immediate problem is formatting (both the datetime and the boolean are wrong), but it is best fixed by parameterization - you should almost never be concatenating values into TSQL:
SqlCommand cmd = new SqlCommand(
"UPDATE CustomerAuthOTP SET IsAuthenticated=1, AuthenticationTime=#now", conn);
cmd.Parameters.AddWithValue("now", now);
cmd.ExecuteNonQuery();
Or with a tool like "dapper":
conn.Execute("UPDATE CustomerAuthOTP SET IsAuthenticated=1, AuthenticationTime=#now",
new { now });

How to find Max element in SQLite?

I need select the maximum ID of PolygonId column. I save my data like this
string sql = "create table Polygons (PolygonId int, PointId int, X double, Y double)";
// Выполнение нашей команды
using (SQLiteCommand command = new SQLiteCommand(sql, m_dbConnection))
{
command.ExecuteNonQuery();
}
int pointId = 1;
for (int i = 0; i < listOfCustomPolygons.Count; i++)
for (int j = 0; j < listOfCustomPolygons[i].listOfVertexes.Count; j++)
{
string strSQL =
string.Format("INSERT INTO Polygons (PolygonId,PointId,X,Y) Values ('{0}','{1}','{2}','{3}')",
i+1,pointId,listOfCustomPolygons[i].listOfVertexes[j].X,
listOfCustomPolygons[i].listOfVertexes[j].Y );
pointId++;
using (SQLiteCommand insertCommand = new SQLiteCommand(strSQL, m_dbConnection))
{
insertCommand.ExecuteNonQuery();
}
}
After this I want select the max value from table Polygons and column PolygonId, but I got an IndexOutOfRangeException. How a can solve this problem?
using (SQLiteConnection connection = new SQLiteConnection("Data Source=" + openFileDialog.FileName + ";Version=3;"))
{
connection.Open();
string selectMaxId = "Select Max(PolygonId) From Polygons";
string selectQuery = "Select * From Polygons";
SQLiteCommand selectMaxCmd = new SQLiteCommand(selectMaxId,connection);
SQLiteDataReader dataReader = selectMaxCmd.ExecuteReader();
int maxId = Convert.ToInt32(dataReader["Select Max(PolygonId) From Polygons"]); // This is don't work! Why?
I found out the solution! It should look like
string selectMaxId = "Select Max(PolygonId) From Polygons";
SQLiteCommand selectMaxCmd = new SQLiteCommand(selectMaxId,connection);
object val = selectMaxCmd.ExecuteScalar();
int maxId = int.Parse(val.ToString());
I hope it can help somebody who face with similar problem)
First of all don't create table every time you run your code :) But you probably know that
You type like this:
int maxId = Convert.ToInt32(dataReader["Select Max(PolygonId) From Polygons"]);
Try this:
string selectMaxId = "Select Max(PolygonId) From Polygons";
SQLiteCommand selectMaxCmd = new SQLiteCommand(selectMaxId,connection);
SQLiteDataReader dataReader = selectMaxCmd.ExecuteReader();
int maxID = -1;
while(dataReader.read())
{
maxID = (int)dataReader.GetValue(0);
}
//This Works for me in WPF C#:
int MaxNum=0;
sqliteCon.Open();
string Query = "SELECT MAX(Promo_No)FROM Promo_File";
SQLiteCommand createCommand = new SQLiteCommand(Query, sqliteCon);
SQLiteDataReader DR = createCommand.ExecuteReader();
while (DR.Read())
{
MaxNum = DR.GetInt16(0);
}
sqliteCon.Close();
I had the same problem!
You have to learn the difference method of SQLiteCommand.
1.SQLiteCommand.ExecuteReader(). Get a SqlDataReader.
2.SQLiteCommand.ExecuteScalar(). Get a single value from the database.
Microsoft Doc:
cmd.CommandText = "SELECT COUNT(*) FROM dbo.region";
Int32 count = (Int32) cmd.ExecuteScalar();

Returning multiple variables from SQL query

My table structure is as follows:
Session
--------------
SessionID (PK)
RoomID
SessionDate
SessionTimeStart
SessionTimeEnd
I have a following query which will always return one row and display in DGV. I use DataAdapter for connection:
DataTable queryResult = new DataTable();
string ConnStr = "Data Source=DUZY;Initial Catalog=AutoRegSQL;Integrated Security=True";
SqlConnection MyConn = new SqlConnection(ConnStr);
MyConn.Open();
//SQL query that returns todays sessions for the given roomID
string query = #"SELECT SessionID, RoomID, SessionDate, SessionTimeStart, SessionTimeEnd" +
" FROM [Session] " +
" WHERE RoomID = #RoomID " +
" AND SessionDate = cast(getdate() as date) ";
SqlCommand command = new SqlCommand(query, MyConn);
command.Parameters.Add("RoomID", SqlDbType.Char).Value = RoomID;
SqlDataAdapter adapter = new SqlDataAdapter(command);
adapter.Fill(queryResult);
I would like to save the query result into multiple strings representing table columns, i.e.
SessionIDstring = query result for SessionID column
RoomIDstring = query result for RoomID column
and so on...
Is it possible to achieve it using one query, or do I have to create 5 queries for each column?
Something similar to this, perhaps, using ADO.NET?
//SQL query that returns todays sessions for the given roomID
string query = #"SELECT SessionID, RoomID, SessionDate, SessionTimeStart, SessionTimeEnd" +
" FROM [Session] " +
" WHERE RoomID = #RoomID " +
" AND SessionDate = cast(getdate() as date) ";
using (var connection = new SqlConnection(ConnStr))
using (var command = new SqlCommand(query, connection))
{
command.Parameters.Add("RoomID", SqlDbType.Char).Value = RoomID;
try
{
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.Read())
{
// Note that reader[x] has the equivalent type to the type
// of the returned column, converted using
// http://msdn.microsoft.com/en-us/library/cc716729.aspx
// .ToString() if the item isn't null is always ok
string SessionIDstring = reader[0].ToString(); // it should be an int
// reading it twice is ok
int RoomID = (int)reader[1]; // it should be an int
string RoomIDstring = reader[1].ToString(); // it should be an int
if (reader.Read())
{
throw new Exception("Too many rows");
}
}
else
{
throw new Exception("No rows");
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
This code was adapted from MSDN ADO.NET Code Examples. I added some usings and made it single row. I don't even want to know why MSDN examples don't go the full length with using.
Note that SqlDataAdapter are built to recover multiple rows/big data and put them in a DataSet. You can use them for single row data, but it's much easier to simply use a SqlDataReader if you only want to fill some variables.
declare #col1 int
declare #col2 varchar(42)
select #col1 = col1
, #col2 = col2
, ....
You could create a class like so...
public class SessionDto
{
public string SessionID {get; set;}
public string RoomID {get; set;}
public string SessionDate {get; set;}
public string SessionTimeStart {get; set;}
public string SessionTimeEnd {get; set;}
}
And then have a method that takes a Room ID and builds your session object
public SessionDto GetSessionData(int roomId)
{
using (var cnn = new SqlConnection(ConnStr))
{
SessionDto sessionDto;
string query = #"SELECT SessionID, RoomID, SessionDate, SessionTimeStart, SessionTimeEnd" +
" FROM [Session] " +
" WHERE RoomID = #RoomID " +
" AND SessionDate = cast(getdate() as date) ";
cnn.Open();
using (var cmd = new SqlCommand(query,cnn))
{
cmd.Parameters.Add("#RoomID", SqlDbType.Char).Value = roomId;
using (var rdr = cmd.ExecuteReader())
{
if (rdr.HasRows)
{
while (rdr.Read())
{
sessionDto = new sessionDto{
SessionID = rdr.GetString(0),
RoomID = rdr.GetString(1),
SessionDate = rdr.GetString(2),
SessionTimeStart = rdr.GetString(3),
SessionTimeEnd = rdr.GetString(4)
};
}
}
}
}
}
return sessionDto;
}
A lot of this is hand typed as I havent got access to VS right now,
but you should get it to work.
Also, I have used rdr.GetString(), there are other methods for GetType().

Categories

Resources