C# SqlDataReader keeps reading - c#

I have a method for getting data out of my SQL Server database. I'm using a reader to get all the data. The problem is that the reader keeps reading and the application doesn't pop up. It is like an infinite loop or something.
public static List<Reservering> GetReserverings()
{
Reservering res = new Reservering();
using (var conn = new SqlConnection(ConnectionString))
{
conn.Open();
const string query = "select b.boekingid, k.naam, bk.incheckdatum, bk.uitcheckdatum, b.hotelid, b.aantal_gasten from boeking b join klant k on k.klantid = b.boekingid join boekingkamer bk on b.boekingid = bk.boekingid where bk.incheckdatum is not null and bk.uitcheckdatum is not null";
SqlCommand selectReserveringen = new SqlCommand(query, conn);
SqlDataReader reader = selectReserveringen.ExecuteReader();
while (reader.Read())
{
res.Id = (int)reader["boekingid"];
res.Naam = (string)reader["naam"];
res.Incheck_datum = (DateTime)reader["incheckdatum"];
res.Uitcheck_datum = (DateTime)reader["uitcheckdatum"];
res.Hotel = (int)reader["hotelid"];
res.Aantal_personen = (int)reader["aantal_gasten"];
}
reader.Close();
}
return GetReserverings();
}
Does anyone know how to fix this problem?

You've got an infinite recursion by calling the method itself at the end:
return GetReserverings();
You could've discovered this by setting a breakpoint in your method and stepping through your code.
You want to return a list of reservations instead:
var result = new List<Reservering>();
// your code...
return result;
And within your while() loop, you'd want to instantiate a new Reservering each iteration, and Add it to the result list.

You should create an instance of Reservering for each record read and store these instances in the List<Reservering>:
public static List<Reservering> GetReserverings() {
List<Reservering> result = new List<Reservering>();
using (var conn = new SqlConnection(ConnectionString)) {
conn.Open();
const string query =
#"select b.boekingid,
k.naam,
bk.incheckdatum,
bk.uitcheckdatum,
b.hotelid,
b.aantal_gasten
from boeking b join
klant k on k.klantid = b.boekingid join
boekingkamer bk on b.boekingid = bk.boekingid
where bk.incheckdatum is not null
and bk.uitcheckdatum is not null";
using (SqlCommand selectReserveringen = new SqlCommand(query, conn)) {
using (SqlDataReader reader = selectReserveringen.ExecuteReader()) {
while (reader.Read()) {
Reservering res = new Reservering();
result.Add(res);
res.Id = Convert.ToInt32(reader["boekingid"]);
res.Naam = Convert.ToString(reader["naam"]);
res.Incheck_datum = Convert.ToDateTime(reader["incheckdatum"]);
res.Uitcheck_datum = Convert.ToDateTime(reader["uitcheckdatum"]);
res.Hotel = Convert.ToInt32(reader["hotelid"]);
res.Aantal_personen = Convert.ToInt32(reader["aantal_gasten"]);
}
}
}
}
return result;
}
Edit: You can try to simplify while loop with a help of object initializing:
...
while (reader.Read()) {
result.Add(new Reservering() {
Id = Convert.ToInt32(reader["boekingid"]),
Naam = Convert.ToString(reader["naam"]),
Incheck_datum = Convert.ToDateTime(reader["incheckdatum"]),
Uitcheck_datum = Convert.ToDateTime(reader["uitcheckdatum"]),
Hotel = Convert.ToInt32(reader["hotelid"]),
Aantal_personen = Convert.ToInt32(reader["aantal_gasten"])
});
}

public static List<Reservering> GetReserverings()
{
List<Reserving> reservings = new List<Reservings>();
using (var conn = new SqlConnection(ConnectionString))
{
conn.Open();
const string query = "select b.boekingid, k.naam, bk.incheckdatum, bk.uitcheckdatum, b.hotelid, b.aantal_gasten from boeking b join klant k on k.klantid = b.boekingid join boekingkamer bk on b.boekingid = bk.boekingid where bk.incheckdatum is not null and bk.uitcheckdatum is not null";
SqlCommand selectReserveringen = new SqlCommand(query, conn);
SqlDataReader reader = selectReserveringen.ExecuteReader();
while (reader.Read())
{
Reservering res = new Reservering();
res.Id = (int)reader["boekingid"];
res.Naam = (string)reader["naam"];
res.Incheck_datum = (DateTime)reader["incheckdatum"];
res.Uitcheck_datum = (DateTime)reader["uitcheckdatum"];
res.Hotel = (int)reader["hotelid"];
res.Aantal_personen = (int)reader["aantal_gasten"];
reservings.add(res);
}
reader.Close();
}
return reservings;
}

Related

SqlDataReader only reads partial data from JSON column

I have the following code but it only reads the last part of the JSON value:
public string GetUsersJson(long systemOrgId)
{
var query = #"DECLARE #OrgId bigint = #systemOrgId
SELECT e.OrgId, e.Id, e.FirstName, e.LastName
FROM [Internal].[Employee] e
WHERE OrgId = #OrgId and IsActive=1
FOR JSON PATH, ROOT('Users');";
var json = ExecuteSqlCommandWithJsonResponse(query, systemOrgId);
return json;
}
private string ExecuteSqlCommandWithJsonResponse(string queryString, long systemOrgId)
{
var result = "";
using (SqlConnection connection = new SqlConnection(_systemConnectionString))
{
using (var cmd = connection.CreateCommand())
{
connection.Open();
cmd.CommandText =queryString;
cmd.Parameters.AddWithValue("#systemOrgId", systemOrgId);
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
result = reader.GetString(reader.GetOrdinal("JSON_F52E2B61-18A1-11d1-B105-00805F49916B"));
}
}
}
}
return result;
}
If I use if instead I get the first part.
if (reader.Read())
{
result = reader.GetString(reader.GetOrdinal("JSON_F52E2B61-18A1-11d1-B105-00805F49916B"));
}
According to the SqlDataReader Class documentation a while (reader.Read()) should be used.
https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqldatareader?view=dotnet-plat-ext-7.0#examples
Adapting the code to look more like the MS example also gives the same result:
private string ExecuteSqlCommandWithJsonResponse(string queryString, long systemOrgId)
{
var result = "";
using (SqlConnection connection = new SqlConnection(_systemConnectionString))
{
var cmd = connection.CreateCommand();
connection.Open();
cmd.CommandText = queryString;
cmd.Parameters.AddWithValue("#systemOrgId", systemOrgId);
var reader = cmd.ExecuteReader();
while (reader.Read())
{
result = reader.GetString(reader.GetOrdinal("JSON_F52E2B61-18A1-11d1-B105-00805F49916B"));
}
reader.Close();
}
return result;
}
Using a standard concatenate strings with += easily solved it. I hope this can help someone else since this information is missing in the examples I have seen.
https://learn.microsoft.com/en-us/dotnet/csharp/how-to/concatenate-multiple-strings#-and--operators
private string ExecuteSqlCommandWithJsonResponse(string queryString, long systemOrgId)
{
var result = "";
using (SqlConnection connection = new SqlConnection(_systemConnectionString))
{
using (var cmd = connection.CreateCommand())
{
connection.Open();
cmd.CommandText =queryString;
cmd.Parameters.AddWithValue("#systemOrgId", systemOrgId);
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
result += reader.GetString(reader.GetOrdinal("JSON_F52E2B61-18A1-11d1-B105-00805F49916B"));
}
}
}
}
return result;
}

SQLDataReader issue with reading null values

I am having problem with SQLDataReader when it comes into situation that I have one row of data, and one or tho columns (fields) have null value.
Can anybody help with this? Null values are related to string, float and datetime datatype.
First method is:
public class SpajanjeCollection:ObservableCollection<Spajanje>
{
public static SpajanjeCollection GetAllSpajanjes()
{
SpajanjeCollection spajanjes = new SpajanjeCollection();
Spajanje spajanje = null;
using (SqlConnection conn = new SqlConnection())
{
conn.ConnectionString = ConfigurationManager.ConnectionStrings["ConnString"].ToString();
conn.Open();
SqlCommand command = new SqlCommand("SELECT Ponude.IdPonude, Ponude.SifraProizvoda, Proizvodi.Naziv, Proizvodi.Opis, Proizvodi.PocetnaCijena, Ponude.PocetakAukcije, Users.UserName, Ponude.PonudjenaCijena, Ponude.ZavrsetakAukcije, Ponude.Status FROM Ponude LEFT OUTER JOIN Users ON Ponude.Kupac = Users.UserName INNER JOIN Proizvodi ON Ponude.SifraProizvoda = Proizvodi.Id", conn);
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
spajanje = Spajanje.GetSpajanjeFromResultSet(reader);
spajanjes.Add(spajanje);
}
}
}
return spajanjes;
}
}
Second method for data reading is:
public static Spajanje GetSpajanjeFromResultSet(SqlDataReader reader)
{
Spajanje spajanje = new Spajanje(Convert.ToInt16(reader["IdPonude"]), Convert.ToInt16(reader["SifraProizvoda"]), Convert.ToString(reader["Naziv"]), Convert.ToString(reader["Opis"]), float.Parse(reader["PocetnaCijena"].ToString()), (DateTime?)reader["PocetakAukcije"], Convert.ToString(reader["UserName"]), float.Parse(reader["PonudjenaCijena"].ToString()), (DateTime?)reader["ZavrsetakAukcije"], Convert.ToString(reader["Status"]));
return spajanje;
}

Add string array to SQL query

I have a string array which consists of identifiers. I want to get some values from SQL using these identifiers . Is there a way of adding them with a string value to SqlCommand parameters?
I want to create a query like:
select CaseList from MasterReportData where Id = 1 OR Id = 2 OR Id = 3
This is my C# code:
public static List<string> GetCaseList(string[] masterIdList)
{
try
{
string query = " select CaseList from MasterReportData where #masterId";
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(query, conn);
cmd.Parameters.AddWithValue("masterId", ***);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
list.Add(reader[0].ToString());
}
}
conn.Close();
}
catch (Exception e)
{
var err= 0;
}
return list;
}
There are many different ways you can go about doing this but I prefer to create a temp table of possible values. That way you can do something like
select CaseList from MasterReportData where Id IN(select Id from tempTable)
The best approach (with sql optimization) would be:
Create your Type:
CREATE TYPE dbo.IntTTV AS TABLE
( Id int )
Your Ids:
var ids = new List<int>
{
1,
2,
3,
}
Create a schema:
var tableSchema = new List<SqlMetaData>(1)
{
new SqlMetaData("Id", SqlDbType.Int) // I think it's Int
}.ToArray();
Create the table in C#
var table = ids
.Select(i =>
{
var row = new SqlDataRecord(tableSchema);
row.SetInt32(0, i);
return row;
})
.ToList();
Create the SQL Parameter
var parameter = new SqlParameter();
parameter.SqlDbType = SqlDbType.Structured;
parameter.ParameterName = "#Ids";
parameter.Value = table;
parameter.TypeName = "dbo.IntTTV";
var parameters = new SqlParameter[1]
{
parameter
};
Slightly change your query (this is just an example:)
string query = "select mrd.CaseList from MasterReportData mrd"
+ " inner join #ids i on mrd.Id = i.id";
public static List<string> GetCaseList(string[] masterIdList)
{
List<string> list = new List<string>();
try
{
string query = "select CaseList from MasterReportData where ";
using (SqlConnection conn = new SqlConnection(connString))
{
int i = 0;
SqlCommand cmd = new SqlCommand(query, conn);
for(i = 0; i < masterIdList.Length; i++)
{
var parm = "#ID" + i;
cmd.Parameters.Add(new SqlParameter(parm, masterIdList[i]));
query += (i > 0 ? " OR " : "") + " Id = " + parm;
}
cmd.CommandText = query;
//cmd.Parameters.AddWithValue("masterId", ***);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
list.Add(reader[0].ToString());
}
}
}
}
catch (Exception e)
{
e.ToString();
}
return list;
}

C# SqlDataReader gets closed

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);
}
}

Invalid attempt to read when no data is present in my MVC controller

When I am executing this, I am getting the following error:
"Invalid attempt to read when no data is present"
I have data in the database but still it is showing like this. Help me.
public ActionResult Index()
{
SqlConnection con = new SqlConnection(connec);
con.Open();
SqlCommand cmd = new SqlCommand("select Title,DateReleased,TheaterName,Name,PhoneNo,Price,userName from vwTicketBooking ", con);
using (SqlDataReader dr = cmd.ExecuteReader())
{
List<TicketBooking> results = new List<TicketBooking>();
while (dr.Read())
newItem = new TicketBooking();
newItem.Title = dr["Title"].ToString();
newItem.DateReleased = Convert.ToDateTime(dr["DateReleased"]);
newItem.TheaterName = dr["TheaterName"].ToString();
newItem.Name = dr["Name"].ToString();
newItem.PhoneNo = dr["PhoneNo"].ToString();
newItem.Price = Convert.ToInt32(dr["Price"]);
newItem.userName = dr["userName"].ToString();
results.Add(newItem);
return View(results);
}
}
I think you need to use {} with your while statement because your code works like;
while (dr.Read())
{
newItem = new TicketBooking();
}
newItem.Title = dr["Title"].ToString();
newItem.DateReleased = Convert.ToDateTime(dr["DateReleased"]);
newItem.TheaterName = dr["TheaterName"].ToString();
...
and after last iteration, your reader will be after the last line, and there is no data to read it. Use it like;
while (dr.Read())
{
newItem = new TicketBooking();
newItem.Title = dr["Title"].ToString();
newItem.DateReleased = Convert.ToDateTime(dr["DateReleased"]);
newItem.TheaterName = dr["TheaterName"].ToString();
...
...
}
Also use using statement with SqlConnection and SqlCommand as well to dispose them automatically.
You are missing the enclosing brackets for your while loop. Your code in effect is only looping the single line newItem = new TicketBooking(); and when the reader finishes reading, you are attempting to use it again by saying newItem.Title = dr["Title"].ToString(); which is giving you the exception as there is nothing to read any further.
while (dr.Read())
{
newItem = new TicketBooking();
newItem.Title = dr["Title"].ToString();
newItem.DateReleased = Convert.ToDateTime(dr["DateReleased"]);
newItem.TheaterName = dr["TheaterName"].ToString();
newItem.Name = dr["Name"].ToString();
newItem.PhoneNo = dr["PhoneNo"].ToString();
newItem.Price = Convert.ToInt32(dr["Price"]);
newItem.userName = dr["userName"].ToString();
results.Add(newItem);
}
return View(results);

Categories

Resources