Debug "ResultView" showing "Enumeration yielded no results"? - c#

I have applied breakpoint and when I click on query "ResultView" its showing data but when I click 2nd time then data is empty and its showing Enumeration yielded no results. It is strange, is there any cache issue or something else? Why it is showing empty when I click after 1 time, its just show data 1st time,
var connectionString = String.Format(#"
Provider=Microsoft.ACE.OLEDB.12.0;
Data Source={0};
Extended Properties=""Excel 12.0 Xml;HDR=YES""
", filePath);
//Creating and opening a data connection to the Excel sheet
using (var conn = new OleDbConnection(connectionString))
{
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandText = "select * from [الحيازات$]";
using (var rdr = cmd.ExecuteReader())
{
//LINQ query - when executed will create anonymous objects for each row
var query =
(from DbDataRecord row in rdr
select row).Select(x =>
{
//dynamic item = new ExpandoObject();
Dictionary<string, string> item = new Dictionary<string, string>();
for (int i = 0; i < x.FieldCount; i++)
{
string data = "" + rdr.GetName(i) + ":{'id':'" + rdr.GetName(i) + "','code':'" + rdr.GetName(i) + "','title':'" + rdr.GetName(i) + "','type':'text','response";
item.Add(data, x[i] + "}");
}
return item;
});
//Generates JSON from the LINQ query
json = JsonConvert.SerializeObject(query, Formatting.Indented).Replace("'", "\"");// break point here

See similar question. Inspecting with the debugger calls Read(), which will try to go to the next row. Does your table only have 1 row?
The first time you view the data (when you can actually see it, not the second time when you get the Exception), are there multiple rows shown? If not, then you have an issue with your query as it is only returning one row.
If there are multiple rows, there may be an issue with using LINQ on a DataReader object. Full transparency, I haven't used LINQ to loop through a SqlDataReader before. This is how I would do it:
using (var rdr = cmd.ExectuteReader())
{
while(rdr.Read())
{
//do something with the first column
Console.WriteLine(rdr[0]);
}
}
If you want to use LINQ, you could always create a datatable to read from.
using (var rdr = cmd.ExectuteReader())
{
DataTable datatable = new DataTable();
datatable.Load(rdr)
}
...
var results = (from row in datatable...

The first time it works displaying a subset of your data. At the index of last successful row + 1 there might be a breaking record.
Then the enumerator will stop working.
In my specific case, calling the ToList() worked fine. (CsvHelper, CS0726)
https://github.com/JoshClose/CsvHelper/issues/1434

Related

Check if a database table contains any rows

I'm loading data into a form with 3 Entry controls.
The object I am using for this is called mySettings, which is an object of SystemSettings, a class and database table in my SQLite database.
So far I have this code, and it works as is.
var db = new SQLiteConnection(dbPath);
Entry txtServer;
txtServer = new Entry { FontSize = 10 };
controlGrid.Children.Add(txtServer, 2, 0);
Grid.SetColumnSpan(txtServer, 4);
SystemSettings mySettings;
mySettings = db.Get<SystemSettings>(0);
txtServer.Text = mySettings.FTPServer;
However, I need to check whether SystemSettings contains any rows in the table before I load values in.
I've seen a few guides online.
Some say use something along the lines of
SQLiteCommand cmd;
cmd = new SQLiteCommand(db);
...
int result = Convert.ToInt32(db.ExecuteScalar)
However, I get an error there saying
SQLiteCommand does not contain any method containing x parameters
no matter how many I pass in (0 or more).
There also doesn't appear to be a method as part of db.
So how can I check whether SystemSettings contains any rows, before trying to use data that doesn't exist?
The pattern below should work. The .ExecuteScalar() method is actually on the command and not the connection.
int count;
using (SQLiteConnection db = new SQLiteConnection("MY_CXN_STRING"))
using (SQLiteCommand cmd = new SQLiteCommand("SELECT COUNT(*) FROM SystemSettings"))
{
db.Open();
count = (int)cmd.ExecuteScalar();
db.Close();
}
bool hasRows = count != 0;
Basically you want to clear
SystemSettings
Try just running a query that returns nothing against the database. For instance:
SystemSettings = $"SELECT * FROM TABLE_NAME WHERE COLUMN_NAME IS 'INVALID_EXPRESSIONdjeiq48724rufnjdrandom stuff'";
Not the most elegant solution by any means, but it works.
What you want to do is to get the first row in you SystemSettings table if any:
You should therefore execute the following Sql Statement (or something similar) and check if a result is returned:
Select * from SystemSettings LIMIT 1;
You can execute the query and check the result like this:
public bool DoesTableContainRows(string tableName, SQLiteConnection connection)
{
var command = new SQLiteCommand($"Select * from {tableName } LIMIT 1;", connection);
var resultReader = command.ExecuteReader();
// check whether or not a row was returned
bool containRows = resultReader.Read();
resultReader.Close();
return containRows;
}
Edit:
Shows how to check if a table contains rows using .NET and Microsoft.Data.Sqlite including better disposing of resources.
public bool DoesTableContainRows(string tableName, SqliteConnection connection)
{
using (var command = new SqliteCommand($"Select * from {tableName } LIMIT 1;", connection))
{
using (var resultReader = command.ExecuteReader())
{
// check whether or not a row was returned
bool containRows = resultReader.Read();
resultReader.Close();
return containRows;
}
}
}

How can I show mutlitple Rows in Visiual Studio 2013 Website project

I'm using C# language and Visual Studio 2013. I'm trying to show multiple rows in my website but it's only showing the first result
I'm trying
String show = "Select Posts from userPosts where Username='John'";
SqlCommand com = new SqlCommand(show, con);
String str = com.ExecuteScalar().ToString();
Response.Write(str);
This is only showing the first result with the user name JOHN but I want them all.
This is because you have used ExecuteScalar() Try it like this (the result is shown in a DataGridView):
String show = "Select Posts from userPosts where Username='John'";
SqlConnection con = new SqlConnection(connStr);
SqlDataAdapter da = new SqlDataAdapter(show,con);
DataSet ds = new DataSet();
da.Fill(ds,"tbl");
dataGridView1.DataSource = ds.Tables[0];
If you don't want to show in DataGridView and just store in a variable use a List<string> like this:
List<string> Posts = new List<string>();
foreach (DataRow item in ds.Tables[0].Rows)
{
Posts.Add(item[0].ToString());
}
Also you can use SqlDataReader as another option.
You are using ExecuteScalar [Executes the query, and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored. ]
Try ExecuteReader.
String show = "Select Posts from userPosts where Username='John';
using (SqlCommand command = new SqlCommand(show, connection))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
for (int i = 0; i < reader.FieldCount; i++)
{
Console.WriteLine(reader.GetValue(i));
}
Console.WriteLine();
}
}
}
BTW You can try light ORM like Dapper https://github.com/StackExchange/dapper-dot-net. It really nicely remove these horrible while loop
ExecuteScalar()- It executes the query, and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored.
https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar(v=vs.110).aspx.
Instead of ExecuteScalar use ExecuteReader

data reader in ado.net

I have a data reader object, which reads through say 4 rows, and I will be looping through the rows. While reading third row, I insert a row inside the same table, will my data reader be able to read the newly inserted row. If not how to achieve this functionality
Here is the code i tried.
AseCommand sessionCmd = null;
//AseCommand selectCmd = null;
AseCommand insertCmd = null;
AseDataReader reader = null;
string retCode = "Nothing returned from the Server";
string insertStatement;
AseConnection conn = null;
conn = new AseConnection("Data Source='" + host + "';Port='" + port + "';UID='" + user + "';PWD='" + password + "';Database=" + db + ";");
conn.Open();
sessionCmd = new AseCommand("select * from dbo.DummyTable", conn);
try
{
reader = sessionCmd.ExecuteReader();
int count = 0;
while (reader.Read())
{
Console.WriteLine(reader.GetString(0));
count++;
if (count == 3)
{
//insert into table
insertCmd = new AseCommand("insert into DummyTable values (5)", conn);
insertCmd.ExecuteReader();
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
I found your question interesting, because I thought the context would along the lines if a row being added from another process, would the current reader see it.
If I had written your test and it did not produce the result I expected, I might come to Stackoverflow and ask: is it possible to read the new row and I just did not do it right? or maybe even get an answer like: it might work sometimes but not always because of xyz...
However, you got answer three, which was 'don't bother us, we didn't sleep well last night.'
In general terms, a DataReader is a read-only forward-reading stream of tabular data sets. It is streaming the results of a query, not monitoring a table...so the query results have already been executed by the database and are being served when called,but not being updated.
Incidentally, what you did was insert a new row using an ExecuteReader command, which returned a new reader...it doesn't modify the outer reader you are looping through. You could read the results of the insert from the new reader...although its not quite clear why you would want to.
Although probably beyond the scope of your test, you might be interested in the concept of Multiple Active Result Sets which does allow you to go back and forth between two results sets on the same connection.

How to validate multi list

I have the following code to select the record from the database:
public List<string>[] Select(string Command)
{
string query = Command;
//Create a list to store the result
List<string>[] list = new List<string>[2];
list[0] = new List<string>();
list[1] = new List<string>();
//Open connection
if (this.OpenConnection() == true)
{
//Create Command
MySqlCommand cmd = new MySqlCommand(query, connection);
//Create a data reader and Execute the command
MySqlDataReader dataReader = cmd.ExecuteReader();
//Read the data and store them in the list
while (dataReader.Read())
{
list[0].Add(dataReader["NIK"] + "");
list[1].Add(dataReader["Password"] + "");
}
//close Data Reader
dataReader.Close();
//close Connection
this.CloseConnection();
//return list to be displayed
return list;
}
else
{
return list;
}
}
I have 2 column in my table, which is NIK and Password and the table has 2 rows which is 1,1 and 2,1.
How do I validate if the list contain NIK = 2 and Password = 1? How do I know if the select statement is successfully get the record from my table? How do I print the multi list into textbox ?
You should consider using Dictionary<string, string> instead of an array of List<string>s.
You can then print all the records:
foreach (var pair in dictionary)
Console.WriteLine(pair.Key + ", " pair.Value);
The first string in every dictionary pair is a key and the second one is a value.
how do i validate if the list contain NIK = 2 and Password = 1 ?
Go through the list and check. For example, using Enumerable.Any.
how do i know if the select statement is successfully get the record from my table ?
If no exception was thrown.
how do i print the multi list into textbox ?
Construct a string from the values returned from the database (e.g. using StringBuilder) and assign it to TextBox.Text.
BTW, you should really consider enclosing the reader and connection in using block. This way, resources will be deterministically freed even in the case of exception.
Also, consider using type-specific getters to read the data from the reader (such as GetString, GetInt32 etc.).

The Page Page_Load Event Vs The Repeater ItemCommand

I'm running some code in Page_Load then I store the results from this code in some local variables.
Now I use this local variables to assign them to the controls inside my repeater item template
The Problem Is >> the page doesn't displays the item template but there's no data bound to it..I think the repeater can't load the data assigned to it in the Page_Load and it get's initialized -life cycle related issues-
Any idea what the problem is exactly ? and how to solve this ?
EDIT
Some example code :
public partial class MyPage: System.Web.UI.Page
{
int UserId = 0;
protected void Page_Load(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MyDbConn"].ConnectionString);
SqlCommand comm = new SqlCommand("SELECT * From Users, conn);
SqlDataReader reader;
conn.Open();
reader = comm.ExecuteReader();
//I'm not sure if I need those two lines:
AllBrandsRptr.DataSource = reader;
AllBrandsRptr.DataBind();
while (reader.Read())
{
UserId = (int)reader["UserId"];
}
conn.Close();
}
}
protected void AllBrandsRptr_ItemCommand(object source, RepeaterCommandEventArgs e)
{
Label LabelTest = (Label)e.Item.FindControl("MyTestLabel");
LabelTest.Text = UserId.ToString();
}
EDIT 2
My Sql SELECT Statement
string command1 = "SELECT Brands.BrandId, Brands.BrandName, Brands.BrandLogo, Brands.BrandWebsite, Brands.IsBrandVisible, Cuisines.CuisineType, VenueTypes.VenueTypeName FROM Brands FULL OUTER JOIN BrandCuisines ON BrandCuisines.BrandId = Brands.BrandId FULL OUTER JOIN Cuisines ON Cuisines.CuisineId = BrandCuisines.CuisineId FULL OUTER JOIN BrandVenueTypes ON BrandVenueTypes.BrandId = Brands.BrandId FULL OUTER JOIN VenueTypes ON VenueTypes.VenueTypeId = BrandVenueTypes.VenueTypeId";
My Filtration Code
conn.Open();
reader = comm.ExecuteReader();
AllBrandsRptr.DataSource = reader;
AllBrandsRptr.DataBind();
while (reader.Read())
{
if (((int)reader["BrandId"]) == BrandId) //this line to pass collecting some info, if I already iterated through the same Id
{
BrandId = (int)reader["BrandId"];
BrandName = (string)reader["BrandName"];
BrandLogo = (string)reader["BrandLogo"];
BrandWebsite = (string)reader["BrandWebsite"];
IsVisible = (bool)reader["IsBrandVisible"];
}
if (reader["CuisineType"] != DBNull.Value)
{
Cuisines += (string)reader["CuisineType"];
}
if (reader["VenueTypeName"] != DBNull.Value)
{
VenueTypes += ", " + (string)reader["VenueTypeName"];
}
conn.Close();
My Initial Problem
How to use in my application a SELECT statement that must return more than one record to show multiple values for a certain field (m:m relation)
You shouldn't manually iterate over the DataReader at all. It is a forward-only tool. Only the Repeater or your while loop may iterate through the results. I believe your immediate problem is that your while loop is exhausting the DataReader before the Repeater renders.
When you call DataBind(), you're instructing the Repeater to render its template for every item in the collection you assigned as its DataSource. So, any filtration would need to happen before. Ideally, you should probably add that filtration logic as a where clause to your SQL statement.
Can you be more specific about the real problem you're trying to solve? It's hard to give you accurate advice otherwise.
Update:
Keep in mind that while(reader.Read()) does not work like an event handler or otherwise similar to how it might semantically sound. In other words, you aren't telling the program to do something when the DataReader is read, you're telling it to start reading through the data immediately (unrelated to the Repeater).
Here's what I suggest you try:
string sql = "Your current SQL here";
string connectionString = "Your connection string here";
// The using block ensures that the connection will be closed and freed up,
// even if an unhandled exception occurs inside the block.
using (SqlConnection conn = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand(sql, conn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
AllBrandsRptr.DataSource = dt;
AllBrandsRptr.DataBind();
var cuisineTypes = from row in dt.AsEnumerable()
select row["CuisineType"];
string cuisines = string.Join(", ", cuisineTypes.Distinct());
var venueTypes = from row in dt.AsEnumerable()
select row["VenueTypeName"];
string venues = string.Join(", ", venueTypes.Distinct());
}
By using a DataTable instead of DataReader, you're able to iterate through the data as many times as necessary. The DataReader is more performant, if a single, forward-only read through the data is all you need, but the DataTable is much more powerful and is helpful in these situations beyond the DataReader's capabilities.
It's worth mentioning that if you care about this project in the long-term and want to make it maintainable, you should consider eventually moving some of this data access code to a separate layer. You should strive to never have SQL statements or direct data access code in your .aspx.cs files.
Then, your code in Page_Load could be strongly typed and easier to work with:
List<Brand> brands = Brand.GetAllBrands();
AllBrandsRptr.DataSource = brands;
AllBrandsRptr.DataBind();
var cuisineTypes = from brand in brands
select brand.CuisineType;
string cuisines = string.join(", ", cuisineTypes.Distinct());
var venueTypes = from brand in brands
select brand.VenueType;
string venues = string.join(", ", venueTypes.Distinct());

Categories

Resources