Losing first record and the values keep changing when loading reader to datatable - asp.net

I load reader to my table like this
connection.Open();
sqlCmd = new SqlCommand(sqlCmd.CommandText, connection);
SqlDataReader sqlReader = sqlCmd.ExecuteReader();
DataTable dt = new DataTable();
sqlReader.Read();
dt.Load(sqlReader);
But it looks like I cannot retrieve the first record of fetch data.
The second problem is when I call the reader several times after that:
string comName = dt.Rows[0]["companyName"].ToString();
//To get address
sqlCmd.CommandText = addr;
sqlCmd.Parameters.AddWithValue("companyName", comName);
using (var addressReader = sqlCmd.ExecuteReader())
{
if (addressReader.Read())
{
Label1.Text = Label1.Text + " " + addressReader["address"].ToString();
}
}
//To get keyProcesses
sqlCmd.Parameters.Clear();
sqlCmd.CommandText = keyProcesses;
sqlCmd.Parameters.AddWithValue("companyName", comName);
using (var keyProcessesReader = sqlCmd.ExecuteReader())
{
if (keyProcessesReader.Read())
{
Label1.Text = Label1.Text + " " + keyProcessesReader.GetString(0);
}
}
But I find out that these reading also may changes the value of my datatable dt above! How could I only load data to dt at the first reading and keep it there without changing any more ?
Ps: In attempt to overcome the second problem, I am trying to store dt values in list
public class CompanyModel
{
public string compnName { get; set; }
public string compnAddress { get; set; }
public string compnKeyProcesses { get; set; }
public string compnStandards { get; set; }
}
then
List<CompanyModel> companies = new List<CompanyModel>();
for(int i = 0; i < dt.Rows.Count; i++)
{
companies.Add(new CompanyModel
{
compnName = dt.Rows[i]["companyName"].ToString(),
compnAddress = dt.Rows[i]["address"].ToString()
});
}
companyRepeater.DataSource = companies;
companyRepeater.DataBind();
Now, how do I access each company name in the list to make query on that name value accordingly, then input the new result to the list?
I tried:
foreach(List<Component> compnName in companies.Contains("companyName")
{
sqlCmd.CommandText = getKey;
sqlCmd.Parameters.AddWithValue("companyName", compnName);
using (var keyReader = sqlCmd.ExecuteReader())
{
if (keyReader.Read())
{
companies.Add(new CompanyModel compnKeyProcesses = keyReader.GetString("key"));
}
}
sqlCmd.CommandText = getstandard;
sqlCmd.Parameters.AddWithValue("companyName", compnName);
using (var standardReader = sqlCmd.ExecuteReader())
{
if (standardReader.Read())
{
companies.Add(new CompanyModel compnStandards = keyReader.GetString("standards"));
}
}

Try this for your first problem
SqlDataAdapter sdr = new SqlDataAdapter(sqlCmd.CommandText, connection);
DataTable dt=new DataTable();
sdr.Fill(dt);
you can display this whole data as a matter of confirmation by taking a datagridview
dataGridView1.DataSource=dt;

Related

Increase data insert performance

We have created a code that loops in to CosmosDb records and inserts values to Sql db. But in the process, the data insertion perfomance is very slow. please help with suggestions, here is the code. This process is taking more than 4 hours for inserting a data of 4000 rows.
namespace PushNotificationUserInsert
{
class Program
{
static void Main(string[] args)
{
Task.Run(async () =>
{
#region Variables
var endpoint = ConfigurationManager.AppSettings["DocDbEndpoint"];
var masterKey = ConfigurationManager.AppSettings["DocDbMasterKey"];
var connetionString = ConfigurationManager.AppSettings["SQL_connetionString"].ToString();
// var useremail = "\"\"";
string path = #"xxxx.txt";
string[] useremails = File.ReadAllLines(path);
List<string> It = useremails.ToList();
var newIt = It.Distinct().ToList();
var channel = "\"msteam\"";
var cnn = new SqlConnection(connetionString);
var cnnInsert = new SqlConnection(connetionString);
string query = null;
cnn.Open();
foreach (var email in newIt)
{
query = "SELECT * FROM c where c.document.bot_js.mail = \"" + email + "\" AND CONTAINS(c.id," + channel + ", true)";
dynamic responses = "";
JSONModel.Rootobject records = null;
string conversationId = "";
//string email = "";
#endregion
#region Reading data from SQL
// cnn.Open();
SqlDataReader dataReader;
String Output = "";
SqlCommand command = new SqlCommand(#"SELECT [ConversatonReferenceJson] FROM [dbo].[ConversationReferences] where emailid like ''", cnn);
//command = new SqlCommand(sql, cnn);
dataReader = command.ExecuteReader();
while (dataReader.Read())
{
Output = dataReader.GetValue(0).ToString();
records = JsonConvert.DeserializeObject<JSONModel.Rootobject>(Output);
}
dataReader.Close();
dataReader.Dispose();
#endregion
string[] readText = File.ReadAllLines(path);
//List<string> It = readText.ToList();
//var newIt = It.Distinct().ToList();
//foreach (string email in newIt)
//{
Console.WriteLine(email);
try
{
#region reading data from Consmos DB
using (var client = new DocumentClient(new Uri(endpoint), masterKey))
{
responses = client.CreateDocumentQuery(UriFactory.CreateDocumentCollectionUri("Cosmosdbname", "cosmosdbtablebame"), query).ToList();
}
#endregion
#region Looping throught each cosmos DB records and insert value in SQL
foreach (var response in responses)
{
conversationId = response.id.Remove(0, 26);
records.conversation.id = conversationId;
cnnInsert.Open();
SqlCommand commInsert = new SqlCommand("INSERT INTO [ConversationReferences] VALUES " +
"(#ChannelId, #UserId, #ConverJson, #ID, #EmailID)", cnnInsert);
commInsert.Parameters.AddWithValue("#ChannelId", "xxxx");
commInsert.Parameters.AddWithValue("#UserId", "tobedeleted");
commInsert.Parameters.AddWithValue("#ConverJson", JsonConvert.SerializeObject(records));
commInsert.Parameters.AddWithValue("#ID", "tobedeleted");
commInsert.Parameters.AddWithValue("#EmailID", email);
commInsert.ExecuteNonQuery();
cnnInsert.Close();
Console.WriteLine("records updated for " + email);
}
#endregion
}
catch (Exception ex)
{
cnnInsert.Close();
throw;
}
finally
{ cnnInsert.Close(); }
Console.ReadKey();
}
}).Wait();
}
}

Disable asp.net dropdownlist specific Iitems

I have a dropdownlist with few items which bind in code behind. I populate dropdownlist from below query.
Select ID, Name, IsGroup from TempTable
i set DataTextField = "Name" and DataValueField = "ID"
Now i want to disable some items based on "IsGroup" value in DataBound event. How can i access this "IsGroup" column.
For Each item As ListItem In dd.Items
If (What i will compare here = "N") Then
item.Attributes.Add("disabled", "disabled")
End If
Next
Regards
protected void Page_Load(object sender, EventArgs e)
{
var data = GetData();
List<ListItem> items = new List<ListItem>();
foreach (DataRow row in data.Rows)
{
var item = new ListItem()
{
Value = row["Id"].ToString(),
Text = row["Name"].ToString()
};
if (row["IsGroup"].ToString() != "N")
{
item.Attributes.Add("disabled", "disabled");
}
items.Add(item);
}
this.DropDownList1.Items.AddRange(items.ToArray());
}
ref: make drop down list item unselectable
You are doing 2 activities
Fetching data from the database
populating the list item and attaching property/properties to the list item element
Method 1 : Primarily to understand the different operations involved.
class SurroundingClass
{
class Example1
{
public int ID { get; set; }
public string Name { get; set; }
public string IsGroup { get; set; }
}
public void PopulateExample1()
{
// Separate Sections for Database and Dropdown Manipulation
// Database operation
var cs = System.Configuration.ConfigurationManager.ConnectionStrings("CS").ConnectionString;
string sql = "Select ID, Name, IsGroup from TempTable";
SqlConnection conn = new SqlConnection(cs);
SqlCommand cmd = new SqlCommand(sql, conn);
var dr = cmd.ExecuteReader();
List<Example1> e1 = new List<Example1>();
while (dr.Read)
{
var e = new Example1();
e.ID = dr.GetInt32(0);
e.Name = dr.GetString(1);
e.IsGroup = dr.GetString(2);
e1.Add(e);
}
dr.Close();
conn.Close();
// Populate Dropdown
foreach (var i in e1)
{
var li = new ListItem(i.Name, i.ID);
if (i.IsGroup == "Y")
li.Attributes.Add("disabled", "disabled");
ddlExample1.Items.Add(li);
}
}
}
Method 2 : Squeezing the operations in Method 1 together
public void PopulateExample2()
{
// Database Operation and Dropdown Manipulation together
var cs = System.Configuration.ConfigurationManager.ConnectionStrings("CS").ConnectionString;
string sql = "Select ID, Name, IsGroup from TempTable";
SqlConnection conn = new SqlConnection(cs);
SqlCommand cmd = new SqlCommand(sql, conn);
var dr = cmd.ExecuteReader();
while (dr.Read)
{
var li = new ListItem(dr.GetString(1), dr.GetInt32(0));
if (dr.GetString(2) == "Y")
li.Attributes.Add("disabled", "disabled");
ddlExample2.Items.Add(li);
}
dr.Close();
conn.Close();
}
Please note that there can be several variations to the solution, this being only one of them.

Web API to query SQL Server and return result is not working as expected

I am trying to connect to SQL Server from the Web API and return a result set as JSON. But my code shown here is not working as expected. I am trying to return the entire query response as a JSON:
[HttpGet]
public HttpResponseMessage Getdetails(string ROOM)
{
string commandText = "SELECT * from [TDB].[dbo].[results_vw] where ROOM = #ROOM_Data";
string connStr = ConfigurationManager.ConnectionStrings["TDBConnection"].ConnectionString;
var jsonResult = new StringBuilder();
using (SqlConnection connection = new SqlConnection(connStr))
{
SqlCommand command = new SqlCommand(commandText, connection);
command.Parameters.Add("#ROOM_Data", SqlDbType.VarChar);
command.Parameters["#ROOM_Data"].Value = ROOM;
connection.Open();
var reader = command.ExecuteReader();
if (!reader.HasRows)
{
jsonResult.Append("[]");
}
else
{
while (reader.Read())
{
jsonResult.Append(reader.GetValue(0).ToString());
}
}
var response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
response.Content = new StringContent(jsonResult.ToString());
connection.Close();
return response;
}
}
This code returns this result:
333838362692368203368203368203362692368203359544362692368203362692368203362692368203368203
Where I am expecting the JSON as
{"data":
[
{"R_ID":"368203","ROOM":"K2"},
{"R_ID":"368203","ROOM":"K2"}
]}
Now I created a model class called DatabaseResult to store the response but I am not sure how I can store the result in to the model class in the controller
public class DatabaseResult
{
public int r_id { get; set; }
public string room { get; set; }
}
The current result is because you are only return the the value from the first column of each row and adding it to the string builder.
Create a new instance of the model and populate it using the values from the reader for each row.
[HttpGet]
public IHttpActionResult Getdetails(string ROOM) {
string commandText = "SELECT * from [TDB].[dbo].[results_vw] where ROOM = #ROOM_Data";
string connStr = ConfigurationManager.ConnectionStrings["TDBConnection"].ConnectionString;
var jsonResult = new StringBuilder();
using (SqlConnection connection = new SqlConnection(connStr)) {
using (SqlCommand command = new SqlCommand(commandText, connection)) {
command.Parameters.Add("#ROOM_Data", SqlDbType.VarChar);
command.Parameters["#ROOM_Data"].Value = ROOM;
connection.Open();
List<DatabaseResult> records = new List<DatabaseResult>();
using (var reader = command.ExecuteReader()) {
while (reader.Read()) {
var row = new DatabaseResult {
r_id = (int)reader["r_id"],
room = (string)reader["room"],
//...other properties.
};
records.Add(row);
}
return Ok(records);
}
}
}
}
The above uses the column names as the indexer to get the values from the reader.

Chnage format return of DotNet

I created web API using dotNet. It work but i got a little problem.
This is my controller
WaybillDataAccessLayer objway = new WaybillDataAccessLayer();
public IEnumerable<Waybill> Get(string id_wb)
{
List<Waybill> lstWaybill = new List<Waybill>();
lstWaybill = objway.GetWaybill(id_wb).ToList();
return lstWaybill;
}
and my Models(WaybillDataAccessLayer)
public IEnumerable<Waybill> GetWaybill(String id_wb)
{
List<Waybill> lswaybill = new List<Waybill>();
using (SqlConnection con = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand("spGetWaybill", con); //Stored procedure on database
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#waybill", id_wb);
con.Open();
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read()) //foreach
{
Waybill wb = new Waybill();
wb.waybill = rdr["waybill"].ToString();
wb.deskripsi = rdr["deskripsi"].ToString();
wb.tanggal = rdr["tanggal"].ToString();
wb.pengirim = rdr["pengirim"].ToString();
wb.lokasi = rdr["lokasi"].ToString();
wb.penerima = rdr["penerima"].ToString();
lswaybill.Add(wb);
}
con.Close();
}
return lswaybill;
}
when i run this API,the output will be like this
[
{
"waybill": "00000093",
"deskripsi": "SPARE PARTS",
"tanggal": "19990727",
"pengirim": "JIEP",
"lokasi": "HO",
"penerima": "JKHO"
}
]
My Question is
how to remove that [] ?
how to add another information like
{
"status" : "sucess",
"data" { }
}
Thankyou for your help.
You're returning a list of WayBill objects. If you don't want the resulting JSON to be an array, then you need to just return a single WayBill, not a List. And if you want to wrap that in more data, then create a type to represent that information, populate an instance of it, and return it.
Since you're retrieving these objects by ID, I'm assuming there should be only one WayBill for any given ID. Thus you can simplify your data access layer.
public Waybill GetWaybill(String id_wb)
{
using (SqlConnection con = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand("spGetWaybill", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#waybill", id_wb);
con.Open();
SqlDataReader rdr = cmd.ExecuteReader();
rdr.Read();
Waybill wb = new Waybill();
wb.waybill = rdr["waybill"].ToString();
wb.deskripsi = rdr["deskripsi"].ToString();
wb.tanggal = rdr["tanggal"].ToString();
wb.pengirim = rdr["pengirim"].ToString();
wb.lokasi = rdr["lokasi"].ToString();
wb.penerima = rdr["penerima"].ToString();
return wb;
}
}
And add the type to wrap your response:
class GetWayBillResponse()
{
public string Status { get; set;}
public WayBill WayBill { get; set; }
}
Note that adding a status here isn't really all that helpful if you're seeing the object, you can assume it was successful. Also, the API would have responded with an HTTP 200 OK status code. So it's really superfluous.
Now your controller becomes:
WaybillDataAccessLayer objway = new WaybillDataAccessLayer();
public GetWayBillResponse Get(string id_wb)
{
GetWayBillResponse response = new GetWayBillResponse();
response.Status = "Success";
response.WayBill = objway.GetWaybill(id_wb);
return response;
}
Note that you can simplify your data access even further. You're manually assigning the result columns to the WayBill object. That's repetitive and boring. If you use an Object Relational Mapper such as Dapper, you can remove a lot of that boiler plate code.
Here's what it'd look like using Dapper:
public Waybill GetWaybill(String id_wb)
{
using (SqlConnection con = new SqlConnection(connectionString))
{
return con.QuerySingle<WayBill>("spGetWaybill", new { waybill = id_web }, commandType: CommandType.StoredProcedure);
}
}

Session variable accessibility

I have a class which creates a session the following way:
Session["UserId"] = UserId; // UserId = 1
In one of the pages on Page_Load, I retrieve the session variable value this way which works fine:
if (Session["UserId"] != null){
var userid = Session["UserId"];
Welcome.Text = "Hello, " + userid;
}
Now I need to use the value of the session variable in my classes as well. I used the following method to get the session value int useridsession = Convert.ToInt32(HttpContext.Current.Session["UserId"]); but it always returns null whereas the session is correctly read using Session["UserId"]; in my code behind file.
The mentioned class:
public static DataTable ManageBookingsDataTable()
{
int useridsession = Convert.ToInt32(HttpContext.Current.Session["UserId"]);
SqlConnection con = new SqlConnection(Database.ConnectionString);
con.Open();
SqlCommand cmd = new SqlCommand("select bookings.id,user_id, start_date, end_date, pets.name AS 'Pet name' from bookings AS bookings left join users AS usr ON bookings.user_id=usr.id AND bookings.user_id=1 left join pets AS pets ON pets.id=bookings.pet_id WHERE bookings.user_id=#userid_session", con);
cmd.Parameters.AddWithValue("#userid_session", useridsession);
SqlDataAdapter sqlDa = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
string id = string.Empty;
string name = string.Empty;
string startdate = string.Empty;
string enddate = string.Empty;
string full_string = string.Empty;
sqlDa.Fill(dt);
if (dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
id = dt.Rows[i]["id"].ToString();
var sdate = dt.Rows[i]["start_date"];
name = dt.Rows[i]["Pet name"].ToString();
startdate = dt.Rows[i]["start_date"].ToString();
enddate = dt.Rows[i]["end_date"].ToString();
full_string = startdate + " to " + enddate + " (" + name + ")";
//CurrentBookings.Items.Add(new ListItem(full_string, id));
}
}
return dt;
}
I diagnosed the problem by adding HttpContext.Current.Session["UserId"] = 1; which proves that when I set the session in the same class, the method works.
My question is how do I access the previously created session from any class?
Session should be available for the session regardless of the class. Why don't you set and get
your session values using the same class? All your session stuff in a one place so it is more neat and tidy as well.
Local.MySession.UserId = UserId; //Set here
int myUserId = Local.MySession.UserId; //Get here
//Something like this??
namespace Local
{
//You can add all session variables to this class
public class MySession
{
public static int UserId
{
get
{
return Convert.ToInt32(HttpContext.Current.Session["userId"] ?? "0");
}
set { HttpContext.Current.Session["userId"] = value.ToString(); }
}
public static string UserEmail //For Example another session variable
{
get { return HttpContext.Current.Session["email"] ?? ""; }
set { HttpContext.Current.Session["email"] = value; }
}
}
}

Resources