DataTable Loop Within a Loop C# - asp.net

I have a nice dataset loop working, but I need to run another loop based on an ID in the parent loop.
I set up a generic list in a separate class, but I'm totally stumped on how to actually call it. I've Googled it but can't find an example I understand.
EDIT:
List Code...
public class BinList
{
public static List<Bin> GetById(int binOrderSiteID)
{
List<Bin> bins = new List<Bin>();
SqlConnection conn;
SqlCommand comm;
SqlDataReader reader;
using (conn = new SqlConnection(myConnectionHere))
{
comm = new SqlCommand("dbo.sl_BinsBySite", conn);
comm.CommandType = CommandType.StoredProcedure;
comm.Parameters.Add(new SqlParameter("#binOrderSiteID", SqlDbType.Int));
comm.Parameters["#binOrderSiteID"].Value = binOrderSiteID;
try
{
conn.Open();
reader = comm.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
Bin b = new Bin();
b.BinQty = reader["binQty"].ToString();
b.BinType = reader["binType"].ToString();
b.BinWasteGroupName = reader["binWasteGroupName"].ToString();
b.BinCollectionFrequencyType = reader["binCollectionFrequencyType"].ToString();
b.BinDeliveryStartDate = reader["binDeliveryStartDate"].ToString();
b.BinEmptyCharge = reader["binEmptyCharge"].ToString();
b.BinRentalCharge = reader["binRentalCharge"].ToString();
b.BinDutyOfCareCharge = reader["binDutyOfCareCharge"].ToString();
b.BinDeliveryCharge = reader["binDeliveryCharge"].ToString();
bins.Add(b);
}
}
}
finally
{
conn.Close();
}
}
return bins;
}
}
This is a repository for each field
public class Bin
{
public string BinQty { get; set; }
public string BinType { get; set; }
public string BinWasteGroupName { get; set; }
public string BinCollectionFrequencyType { get; set; }
public string BinDeliveryStartDate { get; set; }
public string BinEmptyCharge { get; set; }
public string BinRentalCharge { get; set; }
public string BinDutyOfCareCharge { get; set; }
public string BinDeliveryCharge { get; set; }
}
Code to that calls the loops
public class PDFCreator
{
public static int BinOrderID { get; set; }
private int binOrderID = 0;
public PDFCreator(int intBinOrderID)
{
//Lots of code here
//Data conenection/datatable code here
foreach (DataRow row in dt.Rows)
{
//lots of code here
//dont know how to connect up or call the List
something?? = BinList.GetById(Convert.ToInt32(row["binOrderSiteID"].ToString()));
foreach (//somnething here)
}
}
}
Sorry I didn't add my code initially. I didn't want to show it cos I thought it was pants.
Any ideas?
Cheers,
Numb

To call BinList GetById
var binList = BinList.GetById((int)row["binOrderSiteID"]);
foreach (var bin in binList)
{
// do what you need to do with bin variable
}

Related

Passing lists to the view .Net Core

Im looping through all the results from the SQL query in a .Net Core project. here is Model
public class Mymessagesinfo
{
public int MyMessagesCount { get; set; }
public List<int> MessagesIDs { get; set; }
public List<int> MessagesSendersid { get; set; }
public List<string> MessagesSenders { get; set; }
public List<string> MessagesTitles { get; set; }
public List<string> MessagesInformation { get; set; }
public List<string> MessagesStatus { get; set; }
}
I loop through the users messages in my controller then i pass that model to the view
sqlcon.Open();
int? userid = HttpContext.Session.GetInt32("UserID");
SqlCommand sqlcom = new SqlCommand("select * from messages where Messagereceiver=" +userid , sqlcon);
SqlDataReader reader = sqlcom.ExecuteReader();
if(reader.HasRows)
{
int index = 0;
while(reader.Read())
{
string s;
s = reader[0].ToString();
Mymessages.MessagesIDs.Add(int.Parse(s));
Mymessages.MessagesSendersid.Add(int.Parse(reader[1].ToString()));
Mymessages.MessagesTitles.Add(reader[3].ToString());
Mymessages.MessagesInformation.Add(reader[4].ToString());
Mymessages.MessagesStatus.Add(reader[5].ToString());
index++;
}
Mymessages.MyMessagesCount = index;
}
the very first line Mymessages.MessagesIDs.Add(int.Parse(s)); it throws an exception saying System.NullReferenceException: 'Object reference not set to an instance of an object
i wanted to make sure that reader was holding the results so i added int s and checked on it and it was holding the value it was supposed to.
whats going wrong here? is this how we are supposed to pass list-like data to the view?
You need to initlize MessagesIDs in entity Mymessages, like this:
var Mymessages = new Mymessagesinfo()
{
MessagesIDs = new List<int>()
};
Mymessages.MessagesIDs.Add(id);
Or just define the class like this,
public class Mymessagesinfo
{
public int MyMessagesCount { get; set; }
public List<int> MessagesIDs { get; set; } = new List<int>();
public List<int> MessagesSendersid { get; set; } = new List<int>();
public List<string> MessagesSenders { get; set; } = new List<string>();
public List<string> MessagesTitles { get; set; } = new List<string>();
public List<string> MessagesInformation { get; set; } = new List<string>();
public List<string> MessagesStatus { get; set; } = new List<string>();
}
Here is how I would restructure what you have to make it work.
First, your model class:
public class Mymessagesinfo
{
public List<MessageInfo> Messages { get; set; } = new List<MessageInfo>();
}
public class MessageInfo
{
public int ID { get; set; }
public int Senderid { get; set; }
public string Sender { get; set; }
public string Title { get; set; }
public string Information { get; set; }
public string Status { get; set; }
}
With this approach you have a list of message objects, instead of a bunch of lists containing property data.
Here is how I would suggest you load it from SQL Server:
var data = new Mymessagesinfo();
int? userid = HttpContext.Session.GetInt32("UserID");
var messagesTable = new System.Data.DataTable("messages");
using (var sqlcom = sqlcon.CreateCommand())
{
sqlcom.CommandText = $"select * from messages where Messagereceiver='{userid}'";
using (var adapter = new SqlDataAdapter(sqcom))
{
adapter.Fill(messagesTable);
}
}
// we are now done with SQL and have the data in memory...
foreach(DataRow row in messagesTable.Rows)
{
data.Messages.Add( new MessageInfo {
ID = row.Field<int>(0),
Senderid = row.Field<int>(1),
Sender = row.Field<string>(2),
Title = row.Field<string>(3),
Information = row.Field<string>(4),
Status = row.Field<string>(5),
});
}
return View(data);
This is a lot cleaner and by using a DataAdapter and DataTable you minimize the amount of time that the connection to the database is connected.
Here is how you would use this model in an MVC View:
#Model Mymessagesinfo
<div>
<!-- This is where you can display the properties of the message. //-->
<ul>
#foreach(var message in Model.Messages)
{
<li> #message.Title - #message.Id </li>
}
<ul>
<div>

Unable to assign value to Array get set

I am very new to .net. I have a class which has get and set property. Now if I want to assign value to this array , I am facing null reference. I am unable to assign value ORM.a[i] = dr["SUMMARY"].ToString();
public class method1
{
public string[] a{ get; set; }
public double[] b{ get; set; }
}
publiv method1 GetResponseData()
{
int i = 0;
method1 ORM = new method1 ();
foreach (DataRow dr in dtResultHistory.Rows)
{
ORM.a[i] = dr["SUMMARY"].ToString() ;
ORM.b[i] = Convert.ToDouble( dr["AVG_TIME"]);
}
return ORM ;
}
you are facing null exception because you havent created instace of it.
something like
string[] a = new string [size];
If you are not having details about how many element i going to be there , i suggest you make use of List.
Example :
public class method1
{
public method1()
{
a = new List<string>();
b = new List<double>();
}
public List<string> a{ get; set; }
public List<double> b{ get; set; }
}
you code after this will be
public method1 GetResponseData()
{
int i = 0;
method1 ORM = new method1();
foreach (DataRow dr in dtResultHistory.Rows)
{
ORM.a.Add(dr["SUMMARY"].ToString());
ORM.b.Add(Convert.ToDouble( dr["AVG_TIME"]));
}
return ORM ;
}
The error happens because both a and b property hasn't been initialized. Initialized them first in the class constructor:
public class method1
{
public method1() {
this.a = new string[100]; // We take 100 as an example of how many element the property can handle.
this.b = new double[100];
}
public string[] a{ get; set; }
public double[] b{ get; set; }
}

Convert DbContext way to SqlCommand way

Today I have an App which work using EF Core, with the DbContext class and looks like this:
public class RcoreContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(#"Server=(localdb)\mssqllocaldb;Database=rCoreData.TestDb;Trusted_Connection=True;");
}
public DbSet<Hosts> Hosts { get; set; }
public DbSet<Route> Route { get; set; }
}
public class Hosts
{
public int HostsId { get; set; }
public string Host { get; set; }
[NotMapped]
public Dictionary<object, object> Datas { get; set; }
public string DatasJson { get { return JsonConvert.SerializeObject(Datas); } set { Datas = JsonConvert.DeserializeObject<Dictionary<object, object>>(value); } }
}
public class Route
{
public int RouteId { get; set; }
public int HostId { get; set; }
public string RealRoute { get; set; }
public string alias { get; set; }
}
I very like this way because the requests returns are based on existing classes (Hosts and Route in this code).
The SqlCommand way seems more comfortable to use (it seems to be more PHP-like) but seems to return the entries as object. (I read this article)
I would like to know if is it possible to make a mix between the 2 ways and to send a request as a StoredProcedure like SqlCommand do BUT still be based on existing classes for the request return.
Thanks
if you want to use ADO.NET in EF, you just need to get the current connection string and create the sqlcommand as below:
using (var context = new RcoreContext())
{
// creates a Command
var command = context.Database.Connection.CreateCommand();
command.CommandType = commandType;
command.CommandText = sql;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
for (int i = 0; i < reader.FieldCount; i++)
{
Console.WriteLine(reader.GetValue(i));
}
Console.WriteLine();
}
}
}
and if you just want to execute sql or stored procedure, you can also use below in EF
_dbContext.Database.ExecuteSqlCommand(sql, parameters);
_dbContext.Database.SqlQuery<TEntity>(sql, parameters);
using (var connection = context.Database.GetDbConnection())
using (var command = context.Database.GetDbConnection().CreateCommand())
{
command.CommandText = string.Format(sqlQuery, id);
connection.Open();
using (var reader = command.ExecuteReader()){}
}
using (var connection = new SqlConnection(_dbContext.Database.Connection.ConnectionString))
using (var cmd = new SqlCommand())
{
cmd.Connection = connection;
cmd.CommandText = "your query here";
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("#param1", SqlDbType.Int);
cmd.Connection.Open();
cmd.ExecuteNonQuery();
}

How to retrieve the text from a cell in a dynamically generated gridview

I want to get the book name which is in the first column of gridview. I used Template field and added a link button in it. Book name is retrieved from database, thus dynamically wriiten. I want open the selected book in pdf in another page.
public class Book
{
public string Bookn{get;set;}
public string Auth { get; set; }
public string Category { get; set; }
public string Edi { get; set; }
public string Yopub { get; set; }
public string Avai { get; set; }
public string img { get; set; }
}
public class GetData
{
public static List<Book> Getallrecord(string author)
{
List<Book> ob1 = new List<Book>();
SqlConnection con;
SqlCommand com;
string cs = ConfigurationManager.ConnectionStrings["SDL_DBConnectionString"].ConnectionString;
using (con = new SqlConnection(cs))
{
com = new SqlCommand("searchByAuthor3", con);
com.CommandType = CommandType.StoredProcedure;
com.Parameters.AddWithValue("#SAuthor", author + "%");
con.Open();
SqlDataReader rd = com.ExecuteReader();
while (rd.Read())
{
Book bo = new Book();
bo.Bookn = rd["BookName"].ToString();
bo.Auth = rd["Author"].ToString();
bo.Category = rd["Category"].ToString();
bo.Yopub = rd["Yopublication"].ToString();
bo.Edi = rd["Edition"].ToString();
bo.Avai = rd["Available"].ToString();
bo.img = rd["Images"].ToString();
ob1.Add(bo);
}
}
return ob1;
}
}
protected void SAButton_Click(object sender, EventArgs e)
{
string author = TAuthor.Text;
if (Session["ClientLogin"] != null)
{
SAGridView.DataSource=GetData.Getallrecord(author);
SAGridView.DataBind();
}
else
{
Server.Transfer("Login.aspx");
}
}
You can add a hyperlink field in your gridview and redirect to your other page like
<asp:HyperLinkField DataNavigateUrlFields="Bookn"
DataNavigateUrlFormatString="View_Book.aspx?BookNo={0}" Text="View Book" />

how to explicitly set the Order property of class members using XmlElement asp.net

I am trying to serialize my code.
When I set the Order property of class members using XmlElement ASP.Net, I got exception on this line;
XmlSerializer serializer = new XmlSerializer(typeof(HotelListResponse));
Exception is;
Inconsistent sequencing: if used on one of the class's members,the 'Order' property is required on all particle-like members,please explicitly set 'Order' using XmlElement, XmlAnyElement or XmlArray custom attribute on class member '_hotelId'.
Code is:
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
StreamReader responsereader = new StreamReader(response.GetResponseStream());
var responsedata = responsereader.ReadToEnd();
xmldoc = (XmlDocument)JsonConvert.DeserializeXmlNode(responsedata);
xmldoc.Save(#"C:\New folder\myfile.xml");
DataTable dt = new DataTable();
DataRow dr;
dt.Columns.Add("hotelId");
dt.Columns.Add("name");
dt.Columns.Add("address1");
dt.Columns.Add("address2");
dt.Columns.Add("city");
dt.Columns.Add("postalCode");
dt.Columns.Add("countryCode");
dr = dt.NewRow();
XmlSerializer serializer = new XmlSerializer(typeof(HotelListResponse));
Stream reader = new FileStream(#"C:\New folder\myfile.xml", FileMode.Open);
HotelListResponse htype = (HotelListResponse)serializer.Deserialize(reader);
dt.ReadXml(#"C:\New folder\myfile.xml");
foreach(hoteltype ht in htype.hotel){
GridView1.DataSource = dt;
GridView1.DataBind();
}
//responsereader.Close();
//request.GetResponse().Close();
}
}
catch (WebException ex)
{
if (ex.Response == null)
throw new NullReferenceException("WebException response");
throw ex;
}
}
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlRoot("HotelListResponse")]
public class HotelListResponse
{
[System.Xml.Serialization.XmlElementAttribute("hotel")]
public hoteltype[] hotel;
[System.Xml.Serialization.XmlElement(Order = 0)]
public hoteltype[] Items {
get {
return this.hotel;
}
set {
this.hotel = value;
}
}
}
[Serializable]
[XmlType("hoteltype")]
public class hoteltype
{
hoteltype(){}
public int _hotelId;
public string _name;
public string _address1;
public string _address2;
public string _city;
public int _postalCode;
public string _countryCode;
[XmlElement]
public hoteltype[] htype;
[System.Xml.Serialization.XmlElement(Order=1)]
public int hotelId
{
get {
return _hotelId;
}
set{
_hotelId = value;
}
}
[System.Xml.Serialization.XmlElement(Order=2)]
public string name
{
get
{
return _name;
}
set
{
_name = value;
}
}
[System.Xml.Serialization.XmlElement(Order=3)]
public string address1
{
get
{
return _address1;
}
set
{
_address1 = value;
}
}
[System.Xml.Serialization.XmlElement(Order=4)]
public string address2
{
get
{
return _address2;
}
set
{
_address2 = value;
}
}
[System.Xml.Serialization.XmlElement(Order=5)]
public string city
{
get
{
return _city;
}
set
{
_city = value;
}
}
[System.Xml.Serialization.XmlElement(Order=6)]
public int postalCode
{
get
{
return _postalCode;
}
set
{
_postalCode = value;
}
}
[System.Xml.Serialization.XmlElement(Order=7)]
public string countryCode
{
get
{
return _countryCode;
}
set
{
_countryCode = value;
}
}
}
As described in the exception, as soon as you use Order=xx, all of the serializable properties and fields on the class must be ordered. However, it seems that _hotelId may have been intended to be a private backing field. Since XmlSerializer serializes public fields as well, this may be unintentional. If _hotelId really must be public but you don't want it serialized, then you can use XmlIgnore.
I'm guessing your class might look something like:
[System.SerializableAttribute()]
public partial class HotelListResponse
{
[System.Xml.Serialization.XmlElement(Order = 0)]
public string SomeOrderedField
{
get;
set;
}
// ** Problem may be here
// Because the field is public, XmlSerializer will try to serialize this
public int _hotelId;
[System.Xml.Serialization.XmlElement(Order = 1)]
public int HotelId
{
get
{
return _hotelId;
}
set
{
_hotelId = value;
}
}
Edit Yes, that's exactly the problem
Make your backing fields private - that's why you've got the public Property accessors for.
public int _hotelId; => private int _hotelId;
public string _name; => private string _name;
etc.
Edit
[XmlElement(Order=0)]
public hoteltype[] htype;
I would also change it to a property at the same time. Use the automatic backing fields if you are using .NET 3.5 or higher.
[XmlElement(Order=0)]
public hoteltype[] htype
{
get;
set;
}
Edit
If you applied the above systematically, your serializable classes should look like:
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlRoot("HotelListResponse")]
public class HotelListResponse
{
// This is bad practice - never make a backing field public
//[System.Xml.Serialization.XmlElementAttribute("hotel")]
//public hoteltype[] hotel;
// Use the >= .Net 3.5 automatic properties - this way you don't need
// the backing field at all, which will prevent confusion over
// 'what gets serialized'
[System.Xml.Serialization.XmlElement(Order = 0)]
public hoteltype[] Items
{
get;
set;
}
}
[Serializable]
[XmlType("hoteltype")]
public class hoteltype
{
public hoteltype() { }
[System.Xml.Serialization.XmlElement(Order = 0)]
public hoteltype[] htype
{
get;
set;
}
[System.Xml.Serialization.XmlElement(Order = 1)]
public int hotelId
{
get;
set;
}
[System.Xml.Serialization.XmlElement(Order = 2)]
public string name
{
get;
set;
}
[System.Xml.Serialization.XmlElement(Order = 3)]
public string address1
{
get;
set;
}
[System.Xml.Serialization.XmlElement(Order = 4)]
public string address2
{
get;
set;
}
[System.Xml.Serialization.XmlElement(Order = 5)]
public string city
{
get;
set;
}
[System.Xml.Serialization.XmlElement(Order = 6)]
public int postalCode
{
get;
set;
}
[System.Xml.Serialization.XmlElement(Order = 7)]
public string countryCode
{
get;
set;
}
}
And testing the above via a serialize / deserialize cycle like so:
XmlSerializer serializer = new XmlSerializer(typeof(HotelListResponse));
HotelListResponse X = new HotelListResponse();
X.Items = new hoteltype[2];
X.Items[0] = new hoteltype();
X.Items[0].address1 = "address1";
X.Items[1] = new hoteltype();
X.Items[1].address1 = "address2";
using (Stream writer = new FileStream(#"C:\temp\myfile.xml", FileMode.Create))
{
serializer.Serialize(writer, X);
writer.Flush();
}
Stream reader = new FileStream(#"C:\temp\myfile.xml", FileMode.Open);
HotelListResponse htype = (HotelListResponse)serializer.Deserialize(reader);
The following file Deserializes:
<?xml version="1.0"?>
<HotelListResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Items>
<hotelId>0</hotelId>
<address1>address1</address1>
<postalCode>0</postalCode>
</Items>
<Items>
<hotelId>0</hotelId>
<address1>address2</address1>
<postalCode>0</postalCode>
</Items>
</HotelListResponse>

Resources