So I'm attempting to read in values from an existing SQLite database and it seems to initially work but after the query it seems to lose the values when I try to read them in.
What am I doing wrong here?
https://www.youtube.com/watch?v=Yvj6BTjts3M
public ObservableCollection<Asset> GetAllAssets()
{
_DbConn.Open();
var command = _DbConn.CreateCommand();
var allAssets = new ObservableCollection<Asset>();
command.CommandText =
#"
SELECT *
FROM asset
";
using (var reader = command.ExecuteReader())
{
while (reader.HasRows)
{
Asset asset = new Asset();
asset.AssetId = reader.GetInt32(0);
asset.AssetTypeId = reader.GetInt32(1);
asset.Name = reader.GetString(2);
asset.FileLocation = reader.GetString(3);
asset.IsCustom = reader.GetBoolean(4);
asset.AssetSectionId = reader.GetInt32(5);
asset.ThumbFileLocation = reader.GetString(6);
allAssets.Add(asset);
}
}
_DbConn.Close();
return allAssets;
}
The method HasRows() returns true if reader contains one or more rows or false if not, but it does not advance reader to the next row.
You must use the method Read():
while (reader.Read())
......................
Related
I'm working on a project where the customer can make an order of infinite products, I need my code to read every single product ID of his order.
For this to work, it needs to be in a loop, and I could only find ways to make this without a loop, with finite products on the internet.
I tried using SELECT like this:
string selectCod = "SELECT id FROM order";
MySqlCommand selectCodCmd = new MySqlCommand(selectCod, BDconnection);
reader = selectCodCmd.ExecuteReader();
while (reader.Read())
{
}
reader.Close();
But I can't think of anything to put inside the while, I tried using x = reader[0].ToString(); but I only get the last product ID.
If anyone could help me I would appreciate it
Edit1:
Thanks a lot, It worked! Here's the code if anyone has the same problem in future:
string selectCod = "SELECT id FROM OrderItens";
var selectCodCmd = new MySqlCommand(selectCod, BDconnection);
reader = selectCodCmd.ExecuteReader();
var OrderItensId = new List<string>();
while (reader.Read())
{
OrderItensId.Add(reader["id"].ToString());
}
reader.Close();
foreach(string Code in OrderItensId)
{
string CodeAmount = "SELECT amount FROM OrderItens
WHERE id = "+ Code +"";
var CodeAmountCmd = new MySqlCommand(CodeAmount, BDconnection);
reader = CodeAmountCmd.ExecuteReader();
int OrderAmount = 0;
while (reader.Read())
{
OrderAmount = Int32.Parse(reader[0].ToString());
}
reader.Close();
string UpdateStock = "UPDATE Stock
SET amount = amount - "+OrderAmount+"
WHERE id = "+ Code +"";
var UpdateStockCmd = new MySqlCommand(UpdateStock, BDconnection);
reader = UpdateStockCmd.ExecuteReader();
while (reader.Read()) { }
reader.Close();
}
Well, as i understand, you need to get all the products ids from one specific order right?
With this, you only getting all the orders ids from your table orders
string selectCod = "SELECT id FROM order";
First, you will need the order id and i suppose that you have a table called orderItens or something like that..
Then, you get all the itens for that order with a select like this:
string selectCod = "SELECT id FROM orderItens where orderId = #orderId";
Then just create a loop like this
var orderItensIds = new List<int>();
while (reader.Read())
{
orderItensIds.Add(int.Parse(reader["id"]));
}
reader.Close();
return orderItensIds
There you have a list with all the itens id from your order
You are using it right, you just need to put the code var x = reader[0].ToString(); into while loop to let it get all id in all rows.
For example, I will use a listId list to save Id list. You can use it to calculate or insert later.
string selectCod = "SELECT id FROM order";
MySqlCommand selectCodCmd = new MySqlCommand(selectCod, BDconnection);
reader = selectCodCmd.ExecuteReader();
var listId = new List<int>();
while (reader.Read())
{
var x = reader[0].ToString();
listId.Add(int.Parse(x));
}
reader.Close();
// Use this list to any where you want
listId
I am very new to database queries and even more so, Oracle. I am also new to development work and, believe it or not, am creating this an for work purely out of frustration with the current process. Anyway, I am attempting to collect input from a multi-line text box and run a query. Each line corresponds to a single string that needs to be passed into the WHERE statement and the results will be dumped into a data table. Unfortunately, Oracle has still not released its developer tools for VS2019 so I am having to do this the harder way.
UPDATE # 2:
I have completely rebuilt the query since it was not running even when using known working code from another query. Below is what I have pieced together from various places on the interwebs. While debugging, it appears to parse and format the text correctly and pass it into the OracleParameter without issue. I am getting a Missing Expression error but I don't know what I am missing.
var connString =
ConfigurationManager.ConnectionStrings["dB"].ConnectionString;
string query = "SELECT col1, col2, col3, col4 FROM table WHERE col5 IN (";
using (OracleConnection conn = new OracleConnection(connString))
try
{
var input = "";
input = uniLookup.UniList;
var uniList = string.Join(",", Regex.Split(input, #"(?:\r\n|\n|\r)"));
string allParams = uniList;
string formattedParams = allParams.Replace(" ", string.Empty);
string[] splitParams = formattedParams.Split(',');
List<OracleParameter> parameters = new List<OracleParameter>();
using (OracleCommand cmd = new OracleCommand(query, conn))
{
for (int i = 0; i < splitParams.Length; i++)
{
query += #":Uni" + i + ",";
parameters.Add(new OracleParameter(":Uni" + i, splitParams[i]));
{
query = query.Substring(0, (query.Length - 1));
query += ')';
conn.Open();
using (OracleDataReader reader = cmd.ExecuteReader()) <==ERROR
{
if (!reader.HasRows)
{
while (reader.Read())
{
reader.Read();
{
MessageBox.Show(reader.GetString(1));
}
}
}
You can use IN in your where clause in this way to get rows from multiple values as:
string query = "SELECT dummyCol FROM dummytable WHERE altCol IN ("+text+");";
where you just have to change your text as text="'value1','value2','value3'"; this will not produce any syntax error.
You can convert your multi line text into same comma separated values using this :
foreach (String s in textBox1.Text.Split('\n'))
{
text +="'"+ s+"',";
}
text = text.TrimEnd(',');
this will help you achieve what you need. you can ask If there is any confusion.
Your final code will become :
public void GetData()
{
if (string.IsNullOrWhiteSpace(textbox1.Text) || textbox1.Text == "")
{
MessageBox.Show("Please Enter at least 1 Value and Try Again!");
}
else
{
System.Data.DataTable dt = new System.Data.DataTable();
// string[] lines = textbox1.Text.Split('\n');
string text = "";
foreach (String s in textBox1.Text.Split('\n'))
{
text += "'" + s + "',";
}
text = text.TrimEnd(',');
//Connection Credentials
string credentials = "Credentials";
string query = "SELECT dummyCol FROM dummytable WHERE altCol IN ("+text+");";
OracleConnection conn = new OracleConnection(credentials);
try
{
//Open The Connection
conn.Open();
using (OracleCommand cmd = new OracleCommand(query, conn))
{
//Call the Oracle Reader
using (OracleDataReader reader = cmd.ExecuteReader())
{
if (!reader.HasRows)
{
MessageBox.Show("Unable to Retrieve Data");
return;
}
else if (reader.HasRows)
{
reader.Read();
DataRow row = dt.NewRow();
// create variables to accept reader data for each column
// insert data from query into each column here
dt.Rows.Add(row);
}
}
}
}
}
}
I am using the following Access query on C# MVC to compare two tables and return records that fall within the date range and machine selected by the user. The query code runs perfectly on the actual Access database but I guess something is wrong with the connection string and the code to return the results. I am not sure what's wrong with the code and I would appreciate if someone could help me determine what's wrong. Thanks!
C# MVC Controller code:
public ActionResult MissingChecksheets(string startDate, string endDate, string machine)
{
var query = $#"SELECT * FROM [TrackingLog]
WHERE [TrackingLog].[Workcenter] = '{machine}' AND
[TrackingLog].[Complete Date] > #{startDate}# AND
[TrackingLog].[Complete Date] < #{endDate}# AND
[TrackingLog].[Order Item] NOT IN (SELECT [OrderNum] FROM [dbo_Checksheet])";
var sheets = new List<Checksheet>();
using (var con = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Checksheets.accdb;"))
{
using (var command = new OleDbCommand(query, con))
{
con.Open();
using (var reader = command.ExecuteReader())
{
while (reader.NextResult())
{
sheets.Add(new FabChecksheet
{
OrderNum = reader.GetString(0),
PartNum = reader.GetString(1)
});
}
}
}
}
return PartialView(sheets);
}
OleDbDataReader.NextResult() method used to move between result set if the query string has multiple result sets (e.g. more than two SELECT statements, not counting SELECT inside aggregate functions). Since your query has single result set, OleDbDataReader.Read() must be used to move between records:
using (var con = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Checksheets.accdb;"))
{
using (var command = new OleDbCommand(query, con))
{
con.Open();
using (var reader = command.ExecuteReader())
{
// Only single result set, use 'Read' here
while (reader.Read())
{
sheets.Add(new FabChecksheet
{
OrderNum = reader.GetString(0),
PartNum = reader.GetString(1)
});
}
}
}
}
Note that if NextResult() is used, the data reader will move to next result set which has empty data.
Related issue:
Difference between SqlDataReader.Read and SqlDataReader.NextResult
I have no clue why I get an exception. It says that the reader got closed before I try to access it. Why is that so?
Here is the code:
//Load Projects from SQL Server (nothing else)
public SPpowerPlantList loadProjectsFromServer(DateTime timestamp, string note, string sqlServer, string database)
{
SqlConnection sqlConnection = new SqlConnection(String.Format(#"Integrated Security=SSPI;server={0};Initial Catalog={1};", sqlServer, database));
sqlConnection.Open();
string selectstring = "SELECT * FROM [dbo].[tblSPpowerPlant]"; //(WHERE note {0} = " + note + " AND timestamp {1} = " + timestamp;
SqlCommand sqlSelectCommand = new SqlCommand(selectstring, sqlConnection);
sqlSelectCommand.CommandType = CommandType.Text;
sqlSelectCommand.CommandText = selectstring;
SqlDataReader reader;
SPpowerPlantList powerPlantList = new SPpowerPlantList();
reader = sqlSelectCommand.ExecuteReader();
//this line trowhs the exeption
while (reader.Read())
{
foreach (SPpowerPlant powerPlant in powerPlantList)
{
powerPlant.ID = reader.GetInt32(0);
powerPlant.projectName = reader.GetString(1).ToString();
powerPlant.location = reader.GetString(2);
powerPlant.shortName = reader.GetString(3);
powerPlant.numberOfWtgs = reader.GetInt32(4);
powerPlant.mwWtg = reader.GetDouble(5);
powerPlant.mwTotal = reader.GetDouble(6);
powerPlant.projectShareWeb = reader.GetDouble(7);
powerPlant.mwWeb = reader.GetDouble(8);
powerPlant.phase = reader.GetString(9);
powerPlant.phaseNumber = reader.GetString(10);
powerPlant.phaseDescription = reader.GetString(11);
powerPlant.projectProgress = reader.GetDouble(12);
powerPlant.mwDeveloped = reader.GetDouble(13);
powerPlant.projectManager = reader.GetString(14);
powerPlant.spaceUrl = reader.GetString(15);
powerPlant.country = reader.GetString(16);
powerPlant.technology = reader.GetString(17);
powerPlant.state = reader.GetString(18);
powerPlant.allPermits = reader.GetDateTime(19);
powerPlant.cod = reader.GetDateTime(20);
powerPlant.stateSince = reader.GetDateTime(21);
powerPlant.spID = reader.GetInt32(22);
powerPlant.currency = reader.GetString(23);
powerPlant.possibleWtgTypes = reader.GetString(24);
powerPlant.hubHeight = reader.GetString(25);
powerPlant.visibility = reader.GetString(26);
powerPlant.templateName = reader.GetString(27);
powerPlantList.Add(powerPlant);
}
reader.Dispose();
sqlConnection.Close();
}
return powerPlantList;
}
Here is the exception (google translate):
Invalid attempt to Read access because the data reader has been closed.
I tried it with google but had no luck. So any help would be great. Thanks for your time.
BTW Sorry for my english not my native language but I work on it.
the code lines
reader.Dispose();
sqlConnection.Close();
are inside the while(reader.read()) loop.
Also, you better use using instead of calling Dispose() yourself.
public SPpowerPlantList loadProjectsFromServer(DateTime timestamp, string note, string sqlServer, string database)
{
using(var sqlConnection = new SqlConnection(String.Format(#"Integrated Security=SSPI;server={0};Initial Catalog={1};", sqlServer, database)))
{
sqlConnection.Open();
var selectstring = "SELECT * FROM [dbo].[tblSPpowerPlant]"; //(WHERE note {0} = " + note + " AND timestamp {1} = " + timestamp;
var sqlSelectCommand = new SqlCommand(selectstring, sqlConnection);
sqlSelectCommand.CommandType = CommandType.Text;
sqlSelectCommand.CommandText = selectstring;
SPpowerPlantList powerPlantList = new SPpowerPlantList();
using(var reader = sqlSelectCommand.ExecuteReader())
{
while (reader.Read())
{
foreach (SPpowerPlant powerPlant in powerPlantList)
{
powerPlant.ID = reader.GetInt32(0);
powerPlant.projectName = reader.GetString(1).ToString();
powerPlant.location = reader.GetString(2);
powerPlant.shortName = reader.GetString(3);
powerPlant.numberOfWtgs = reader.GetInt32(4);
powerPlant.mwWtg = reader.GetDouble(5);
powerPlant.mwTotal = reader.GetDouble(6);
powerPlant.projectShareWeb = reader.GetDouble(7);
powerPlant.mwWeb = reader.GetDouble(8);
powerPlant.phase = reader.GetString(9);
powerPlant.phaseNumber = reader.GetString(10);
powerPlant.phaseDescription = reader.GetString(11);
powerPlant.projectProgress = reader.GetDouble(12);
powerPlant.mwDeveloped = reader.GetDouble(13);
powerPlant.projectManager = reader.GetString(14);
powerPlant.spaceUrl = reader.GetString(15);
powerPlant.country = reader.GetString(16);
powerPlant.technology = reader.GetString(17);
powerPlant.state = reader.GetString(18);
powerPlant.allPermits = reader.GetDateTime(19);
powerPlant.cod = reader.GetDateTime(20);
powerPlant.stateSince = reader.GetDateTime(21);
powerPlant.spID = reader.GetInt32(22);
powerPlant.currency = reader.GetString(23);
powerPlant.possibleWtgTypes = reader.GetString(24);
powerPlant.hubHeight = reader.GetString(25);
powerPlant.visibility = reader.GetString(26);
powerPlant.templateName = reader.GetString(27);
powerPlantList.Add(powerPlant);
}
}
}
}
return powerPlantList;
}
If you remove that foreach part you can see the problem.
You check if the reader is open
you iterate over the powerplant list, by the way this is reassigning each powerPlant to the same record in the reader
You close and dispose of the reader
Now you check if it is open again at the top of the while which throws the exception
I believe you want to create a new list of SPpowerPlant objects from your reader. You should change your code to the following which does that and releases the reader. Note that you should wrap all your Disposable objects in using statements like with the reader below.
using(var reader = sqlSelectCommand.ExecuteReader()) // closes and disposes reader once it is out of scope
{
while (reader.Read())
{
var powerPlant = new SPpowerPlant();
powerPlant.templateName = reader.GetString(27);
//// rest of calls to populate your item
SPpowerPlantList.Add(powerPlant);
}
}
This is my code:
db.Open();
string updateString = "SELECT TOP 1 RTRIM(kol) kol, RTRIM(adres) adres, RTRIM(numwave) numwave FROM sorters WHERE kodprod=#kodprod AND sorter_kod=#sorter AND moved_ok IS NULL ORDER BY CAST(kol as int)";
try
{
SqlCommand command = new SqlCommand(updateString, db);
//command.Parameters.AddWithValue("#numdoc", NumDoc);
command.Parameters.AddWithValue("#kodprod", KodProd.Id);
command.Parameters.AddWithValue("#sorter", SorterKod);
SqlDataReader reader = command.ExecuteReader();
reader.Read();//here error
Kol = reader["kol"].ToString();
Adres = reader["adres"].ToString();
NumWave = reader["numwave"].ToString();
NumDoc = reader["numdoc"].ToString();
reader.Close();
}
catch (Exception ex)
{ }
Why do I get this error when I run my code?:
Invalid attempt to read when no data is present
You can check whether the DataReader is ready to fetch the rows
if(reader.HasRows)
{
//do the coding here
}
I believe the error will in fact occur on the next line, viz when you access the reader via the index [] operator. What you need to do is check the result of reader.Read() before accessing it:
if (reader.Read())
{
Kol = reader["kol"].ToString();
Adres = reader["adres"].ToString();
NumWave = reader["numwave"].ToString();
NumDoc = reader["numdoc"].ToString();
}
Since you are only returning a maximum of one row (TOP 1) there will either be zero or one rows.
you should do a while loop to check reader contain data. You can also use IF if you are sure the query return only one row. If more than one row you should use While. In your case IF also do the job because you are only taking TOP1
string updateString = "SELECT TOP 1 RTRIM(kol) kol, RTRIM(adres) adres,
RTRIM(numwave) numwave FROM sorters WHERE
kodprod=#kodprod AND sorter_kod=#sorter
AND moved_ok IS NULL ORDER BY CAST(kol as int)";
try
{
SqlCommand command = new SqlCommand(updateString, db);
//command.Parameters.AddWithValue("#numdoc", NumDoc);
command.Parameters.AddWithValue("#kodprod", KodProd.Id);
command.Parameters.AddWithValue("#sorter", SorterKod);
SqlDataReader reader = command.ExecuteReader();
while(reader.Read())
{
Kol = reader["kol"].ToString();
Adres = reader["adres"].ToString();
NumWave = reader["numwave"].ToString();
NumDoc = reader["numdoc"].ToString();
}
reader.Close();
}
Use reader.HasRows
string updateString = "SELECT TOP 1 RTRIM(kol) kol, RTRIM(adres) adres, RTRIM(numwave) numwave FROM sorters WHERE kodprod=#kodprod AND sorter_kod=#sorter AND moved_ok IS NULL ORDER BY CAST(kol as int)";
try
{
SqlCommand command = new SqlCommand(updateString, db);
//command.Parameters.AddWithValue("#numdoc", NumDoc);
command.Parameters.AddWithValue("#kodprod", KodProd.Id);
command.Parameters.AddWithValue("#sorter", SorterKod); SqlDataReader
reader = command.ExecuteReader();
if(reader.HasRows)
while(reader.Read())//here error
{
Kol = reader["kol"].ToString();
Adres = reader["adres"].ToString();
NumWave = reader["numwave"].ToString();
NumDoc = reader["numdoc"].ToString();
}
reader.Close();
}
catch{}
EDIT: sorry for the bad formatting, posting code from the Android app is a mess.
EDIT: See Microsoft example here