Repeated values in list in while(reader.Read()) {} - c#

[WebMethod]
public List<reports> getMyReports( int user_id )
{
string cs = ConfigurationManager.ConnectionStrings["ReportDB"].ConnectionString;
using (SqlConnection con = new SqlConnection(cs))
{
SqlCommand cmd = new SqlCommand("getAllReportsByUserID", con);
cmd.CommandType = CommandType.StoredProcedure;
List<reports> repers = new List<reports>();
//users[][] liser = new users[][];
SqlParameter user_id_parameter = new SqlParameter("#user_id", user_id);
cmd.Parameters.Add(user_id_parameter);
reports report = new reports();
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
report.id = Convert.ToInt32(reader["id"]);
report.title = reader["title"].ToString();
report.description = reader["description"].ToString();
report.anonymous = (bool)reader["anonymous"];
report.location = reader["location"].ToString();
report.status = reader["status"].ToString();
report.category = reader["category"].ToString();
report.date = (DateTime)reader["date"];
report.picture_url = reader["picture_url"].ToString();
report.admin_id = Convert.ToInt32(reader["admin_id"]);
repers.Add(report);
}
return repers;
}
}
I have the top function that calls the following stored procedure:
CREATE Proc [dbo].[getAllReportsByUserID]
#user_id int
as
Begin
Select
id,
title,
description,
anonymous,
location,
status,
category,
date,
picture_url,
admin_id
from reports
where user_id = #user_id
End
I have tested the procedure individually and it works fine. Yet, when I test the WebService created above I get a list with the last value duplicated along the whole list.
Can someone please help me figure out why do I get the same (last)value repeated over and over again?

By creating the report object before the loop and reusing it repeatedly, you insert a reference to that same object multiple times in your list.
You should create the report object inside your loop:
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
reports report = new reports();
report.id = Convert.ToInt32(reader["id"]);
report.title = reader["title"].ToString();
report.description = reader["description"].ToString();
report.anonymous = (bool)reader["anonymous"];
report.location = reader["location"].ToString();
report.status = reader["status"].ToString();
report.category = reader["category"].ToString();
report.date = (DateTime)reader["date"];
report.picture_url = reader["picture_url"].ToString();
report.admin_id = Convert.ToInt32(reader["admin_id"]);
repers.Add(report);
}
return repers;

Related

C# SqlDataReader keeps reading

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

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

Procedure or function 'usp_hotelRoom' expects parameter '#name', which was not supplied

Can somebody help me debug my code?
Basically I have created a stored procedure and I want to call that stored procedure inside my website (ASP.NET).
This code is for my stored procedure:
CREATE PROCEDURE usp_hotelRoom
#country VARCHAR(50),
#name VARCHAR(50)
AS
BEGIN
SELECT
Room.roomID, Room.roomName, Room.type, Room.capacity, Room.roomSize,
Room.description, Room.remarks, Room.services, Room.photo,
Room.price, Hotel.name
FROM
Room
INNER JOIN
Hotel ON Hotel.orgEmail = Room.orgEmail
WHERE
country = #country
AND Hotel.name = #name;
END
EXEC usp_hotelRoom 'singapore', 'marina bay sands';
This code is for calling the stored procedure:
public static List<Room> getHotelRoomByCountry(string country, string name)
{
SqlConnection con = new SqlConnection(conStr);
try
{
SqlCommand command = new SqlCommand();
command.Connection = con;
command.CommandType = System.Data.CommandType.StoredProcedure;
command.CommandText = "usp_hotelRoom";
var paramname = new SqlParameter
{
ParameterName = "#country",
Value = country
};
command.Parameters.Add(paramname);
var paramhotel = new SqlParameter
{
ParameterName = "#hotel.name",
Value = name
};
command.Parameters.Add(paramhotel);
con.Open();
SqlDataReader reader = command.ExecuteReader();
List<Room> rooms = null;
if (reader.HasRows)
rooms = new List<Room>();
while (reader.Read())
{
rooms.Add(
new Room()
{
RoomID = reader["roomID"].ToString(),
RoomName = reader["roomName"].ToString(),
Type = reader["type"].ToString(),
Capacity = reader["capacity"].ToString(),
RoomSize = reader["roomSize"].ToString(),
Desc = reader["description"].ToString(),
Remarks = reader["remarks"].ToString(),
Services = reader["services"].ToString(),
Pictures = reader["photo"].ToString(),
Price = reader["price"].ToString(),
});
}
reader.Close();
return rooms;
}
finally
{
con.Close();
}
}
Hope someone can help me. I would appreciate it on your work!
I try to do it by myself and doesn't work, until I try to add new class attributes inside of the Room class (Hotel.Name)
Thanks!
Change this line of code
ParameterName = "#hotel.name"
to
ParameterName = "#name"

How can I return a stored procedure's result as XML?

I coded a web service connecting to MS-Sql server and getting the results from a stored procedure. My below code is getting only the first result of procedure, but I need all results in the response xml file. I think that I need to use data adapter, data reader, data fill, etc.. something like this. But I could not succeed. I would appreciate any help:
PS: Info.cs class already created.
[WebMethod]
public Info NumberSearch2(string no)
{
Info ourInfo = new Info();
string cs = ConfigurationManager.ConnectionStrings["DBBaglan"].ConnectionString;
using (SqlConnection Con = new SqlConnection(cs))
{
SqlCommand cmd = new SqlCommand(cmdText: "NumberSearch", connection: Con)
{
CommandType = CommandType.StoredProcedure
};
SqlParameter parameter = new SqlParameter
{
ParameterName = "#no",
Value = no
};
cmd.Parameters.Add(parameter);
Con.Open();
SqlDataReader dr = cmd.ExecuteReader();
DataSet ds = new DataSet();
while (dr.Read())
{
ourInfo.PartNo = dr["PartNo"].ToString();
ourInfo.BrandNo = dr["BrandNo"].ToString();
ourInfo.Manufacturer = dr["Manufacturer"].ToString();
ourInfo.Country = dr["Country"].ToString();
ourInfo.ReferenceNo = dr["ReferenceNo"].ToString();
}
}
return ourInfo;
}
After #David 's recommendation:
[WebMethod]
//public Info NumberSearch2(string no)
public List<Info> NumberSearch2(string no)
{
Info ourInfo = new Info();
var ourInfos = new List<Info>();
string cs = System.Configuration.ConfigurationManager.ConnectionStrings["DBBaglan"].ConnectionString;
using (System.Data.SqlClient.SqlConnection Con = new System.Data.SqlClient.SqlConnection(cs))
{
System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(cmdText: "NumberSearch", connection: Con)
{
CommandType = System.Data.CommandType.StoredProcedure
};
System.Data.SqlClient.SqlParameter parameter = new System.Data.SqlClient.SqlParameter
{
ParameterName = "#no",
Value = no
};
cmd.Parameters.Add(parameter);
Con.Open();
System.Data.SqlClient.SqlDataReader dr = cmd.ExecuteReader();
DataSet ds = new DataSet();
while (dr.Read())
{
var ourInfos = new Info();
ourInfo.PartNo = dr["PartNo"].ToString();
ourInfo.BrandNo = dr["BrandNo"].ToString();
ourInfo.Manufacturer = dr["Manufacturer"].ToString();
ourInfo.Country = dr["Country"].ToString();
ourInfo.ReferenceNo = dr["ReferenceNo"].ToString();
ourInfos.Add(ourInfo);
}
}
return ourInfos;
}
You're returning a single Info object. If you want a collection of them, return a List<Info> instead. Change the method signature:
public List<Info> NumberSearch2(string no)
Declare the object to return:
var ourInfos = new List<Info>();
Within your loop, add each record to the list:
while (dr.Read())
{
var ourInfo = new Info();
ourInfo.PartNo = dr["PartNo"].ToString();
ourInfo.BrandNo = dr["BrandNo"].ToString();
ourInfo.Manufacturer = dr["Manufacturer"].ToString();
ourInfo.Country = dr["Country"].ToString();
ourInfo.ReferenceNo = dr["ReferenceNo"].ToString();
ourInfos.Add(ourInfo);
}
And return the list:
return ourInfos;

Passing value in IEnumerable method

net mvc c#. I have created model for view. I can receive all rows from the table but when I try to pass value in method which is return list is not working
Here is my code
Controller class
public ActionResult Index()
{
TechnicianDBO db = new TechnicianDBO();
List<Technician> technicians = db.technicians.ToList();
return View(technicians);
}
[HttpPost]
public ActionResult Index(int Postcode)
{
TechnicianDBO db = new TechnicianDBO();
List<Technician> technicians = db.Jobtechnicians(Postcode).ToList();
return View(technicians);
}
Db class
public IEnumerable<Technician> Jobtechnicians(int postcode)
{
string connectionString = ConfigurationManager.ConnectionStrings["testConnect"].ConnectionString;
List<Technician> Jobtechnicians = new List<Technician>();
using (SqlConnection con = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand("spGetTechnicianByPostcode", con);
con.Open();
SqlParameter paramId = new SqlParameter();
paramId.ParameterName = "#postcode";
paramId.Value = postcode;
cmd.Parameters.Add(paramId);
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
Technician technician = new Technician();
technician.Id = Convert.ToInt32(dr["techId"]);
// technician.Username = dr["techUsername"].ToString();
technician.Firstname = dr["techFirstname"].ToString();
technician.Lastname = dr["techLastname"].ToString();
technician.LandlineNo = dr["landlineNo"].ToString();
technician.MobileNo = dr["mobileNo"].ToString();
technician.Address1 = dr["address1"].ToString();
technician.Address2 = dr["address2"].ToString();
technician.Postcode = Convert.ToInt32(dr["postcode"]);
technician.Email = dr["email"].ToString();
technician.Fax = dr["fax"].ToString();
technician.Profession = Convert.ToInt32(dr["ProfessionId"]);
Jobtechnicians.Add(technician);
}
return Jobtechnicians;
}
}
you need to give CommandType
SqlCommand cmd = new SqlCommand("spGetTechnicianByPostcode", con);
cmd.CommandType = CommandType.StoredProcedure;
and also when you call .ToString() you better check whether that column value null or not if that column allow null in your table

Categories

Resources