Loading class as a list - c#

I have a class
public class Orders
{
public Orders() {}
private string _idOrder;
private string _totalPrice;
public string idOrder
{
get{ return _idOrder;}
set { _idOrder = value;}
}
public string totalPrice
{
get { return _totalPrice; }
set { _totalPrice = value; }
}
}
I am loading the list from database like this
while (dr.Read())
{
Orders.idOrder = dr["IdOrder"].ToString();
Orders.totalPrice= dr["totalPrice"].ToString();
}
It's is showing me only last record. How can I load all the orders and retrieve them back by foreach loop?

Create a list :-)
List<Order> orders = new List<Order>();
while (dr.Read())
{
Order order = new Order();
order.idOrder = dr["IdOrder"].ToString();
order.totalPrice= dr["totalPrice"].ToString();
orders.Add(order);
}
As you see, I renamed your class from Orders to Order, because that's what it really represents: One order. To have more orders, you need to put those single orders into a list.

It's only showing you the one item, because you're only changing properties on the one item, not instantiating a new one:
var results = new List<Order>();
while (reader.Read())
{
var order = new Order
{
Id = (int)reader["IdOrder"],
TotalPrice = (decimal)reader["totalPrice"]
};
results.Add(order);
}

I think you are looking for something like this:
IEnumberable<Order> FetchOrders()
{
while(dr.Read())
yield return new Order {
idOrder=dr["IdOrder"].ToString(),
totalPrice=dr["totalPrice"].ToString()
});
}

That Orders class represents a single order! If what you need is a list of orders then I suggest you rename that class to Order, and then create a List<Order> (a list of order-objects) and populate that from your query results.
Also (forgive me for being pernickety) "idOrder" is not a good field name. The standard approaches are "orderId" or just plain old "Id" (ID, or even id). Likewise I would expect the price-of-ONE-order to be called just "amount", or even "price"... not "totalPrice"... it'll be too confusing when you come to total-up the totalPrices... get my drift?
Cheers. Keith.

I don't see how that will compile. Orders.idOrder is not a static property, it's an instance property.

If i understand you right you want to use something like this:
List<Order> = new List<Order>();
while (dr.Read())
{
Order newOrder = new Order();
newOrder.idOrder = dr["IdOrder"].ToString();
newOrder.totalPrice= dr["totalPrice"].ToString();
orderList.Add(newOrder);
}

Notice this that I just discuss more for #Grook Answer. I Think it is so near to what to want.
IEnumberable<Order> FetchOrders()
{
while(dr.Read())
yield return new Order {
idOrder=dr["IdOrder"].ToString(),
totalPrice=dr["totalPrice"].ToString()
});
}
Then You can easily use foreach loop
Foreach(Order order in GetOrders())
{
doSomething(order);
}
Is it clear?

Related

Get property value of object in an list

I want to get an property value from an object that is in a list and put it into textbox.text
Below i have an example of my code:
The object:
public class Incident
{
public int Incident_id { get; set; }
public string Description { get; set; }
public string Caller { get; set; }
}
Below is my code in my form class:
List<Incident> incidentById = new List<Incident>();
incidentById = db.GetIncidentById(ID);
when my list is filled i want to put the string Caller into an textbox somewhat like below:
textBoxCaller.Text = incidentById[1].Caller;
I'm stuck at this point so i hope someone can help me out.
Thanks!
EDIT:
public List<Incident> GetIncidentById(int id)
{
using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(Helper.CnnVal("IncidentLog")))
{
var output = connection.Query<Incident> ($"select * from Incidents where Incident_id like #id", new { id = "%id%" }).ToList();
return output;
}
}
I wasn't passing the right value into my query
this did the trick!
What you want is $"select * from Incidents where Incident_id = #id", new { id }
do you want first value should go?
check like.
if(incidentById.Count>0)
{
textBoxCaller.Text = incidentById.First().Caller;
}
// or you can join all Caller in list like
if(incidentById.Count>0)
{
textBoxCaller.Text = string.join(",",incidentById.Select(x=>x.Caller));
}
The issue that you are facing is that you are trying to access the second element in the list when there are not two or more elements in the list. If you are trying to access the first element in the list, then you could do either
textBoxCaller.Text = incidentById[0].Caller;
or
textBoxCaller.Text = incidentById.First().Caller;
If you do in fact want the second element of the list, then you should be checking to verify that it's length is at least two:
if(incidentById.Count >= 2)
{
...
}
Finally, as mentioned in a comment, you should rename GetIncidentById to something that makes clear it is returning a list, like GetIncidentsById or something similar.

unwanted object property changed when changing another object property c#

from what i understand in other posts i know that my objects use same place in memory but how to separate these objects?
i tried to use new but it didn't work or i didn't used it correctly.
Note that i didnt paste setter and getter here.
class Supermarket
{
List<Product> _products = new List<Product>{ };
List<Customer> _customers = new List<Customer>{ };
}
class Customer
{
List<Product> _purchased= new List<Product>{ };
}
class Product
{
string _id;
string _name;
DateTime _expireDate;
int _cost;
int _count;
}
i add one Product in one Method.
Product product = new Product(...);
supermarket.Products.Add(product);
and in another method i want to copy the Product from Supermarket.Products
to Supermarket.Customers.Purchased. so i want a copy but i cant get it.
here i want to make Copy but it does not work.
Product product = supermarket.Products[productIndex];
supermarket.Customers[customerIndex].Purchased.Add(product);
now the problem is when i change Product properties in Customer class , Product properties inside Supermarket will change too.
for example
supermarket.Customers[customerIndex].Purchased.Last().Count = ...
//now the Product supermarket.Products[productIndex] will change too witch is unwanted
The reason why it is not working is because you are doing shallow copy by just adding the pointer of product object into the list, not all properties. So if you change one, another will be affected accordingly.
You can use deep copy following this answer, but this way you have to mark your class as [Serializable]. The simplest way which I think is to use Json serializer:
public static class CloneHelper
{
public static T Clone<T>(T source)
{
var serialized = JsonConvert.SerializeObject(source);
return JsonConvert.DeserializeObject<T>(serialized);
}
}
var copyProduct = CloneHelper.Clone<Product>(product);
Or simply, you can manage by yourself as the below code, then it works:
Product product = supermarket.Products[productIndex];
Product copyProduct = new Product() {
Id = product.Id,
Name = product.Name,
ExpireDate = product.ExpireDate,
Cost = product.Cost,
Count = product.Count
};
supermarket.Customers[customerIndex].Purchased.Add(copyProduct);

Dynamically select property in Linq query

I am facing one issue with linq query in c# , my linq query as per below
list = (from row in dt.AsEnumerable()
select new Perfmon
{
id = row.Field<long>("id"),
counter1 = row.Field<string>("counter"),
}).ToList();
I have one perfmon class and it contains properties like (id, counter1, counter2 ...)
there are more then 20 counters now i have developed sql query to select id and counter based on passed countername in parameter e.g. if i have passed counter1 then it will select id , counter1 (renamed as counter) only
if i will use switch case here then it will have 20 witch case, can anyone please help me how can bind property dynamically in linq?
Thanks in advance.
You can make your Perfmon class backed by a dictionary rather than fields per properties. like:
class Perfmon
{
private readonly Dictionary<string, string> _counters = new Dictionary<string, string>();
public Perfmon(params KeyValuePair<string, string>[] knownCounters)
{
foreach (var knownCounter in knownCounters)
{
SetCounter(knownCounter.Key, knownCounter.Value);
}
}
public void SetCounter(string name, string value)
{
_counters[name] = value;
}
protected string GetCounterValue(string name)
{
if (_counters.ContainsKey(name))
return _counters[name];
else
return null;
}
public string Counter1 { get { return GetCounterValue("Counter1"); } }
public string Counter2 { get { return GetCounterValue("Counter2"); } }
public string Counter3 { get { return GetCounterValue("Counter3"); } }
}
The constructor is there so you can easily use it in your query like:
var counterName = "Counter2";
list = (from row in dt.AsEnumerable()
select new Perfmon(new KeyValuePair<string, string>(counterName, row.Field<string>("counter")))
{
id = row.Field<long>("id")
}).ToList();
You can also use Dynamic Linq. The essence is to parse your string and convert it in to expression trees. See here for more details
http://weblogs.asp.net/rajbk/archive/2007/09/18/dynamic-string-based-queries-in-linq.aspx
I think you should look into the System.Reflection namespace. Sure, you want to use it within a linq query, but the thing you can't seem to do, for now, is to dynamically extract a field/property from a class.
Try to use it outside a linq query, and then you'll find a way to integrate it into your query.

What is the eqivalent to a SQL "in" clause here?

I'm new to LINQ and I've been at this for hours now. I have a List<> of objects where one of the objects properties is a List of selected categories. I also have, outside of the objects, a List representing a subset of categories and I want to return all objects which contain at least one category that is also in the subset as illustrated in the following pseudo code (not my actual code)
List<string> subset = cat, dog, mouse
List<myclass> myclasses =
{name:alphie, category:[cat,elephant]},{name:sally, category:[fish]}, {name:bob, category:[dog, mouse]}
In the above example I need to return alphie and bob since they both have at least one category that's in my subset.
The only solution so far is to get a list of both and then use expensive foreach loops to go through and compare. I'm sure LINQ must provide a more efficient way to achieve the same?
More details (I think my pseudo code is not detailed enough)
public class RadioProgram {
...
private List<string> _category = new List<string>();
public List<string> Category { get { return _category; } set { _category = value; } }
...
}
public class Category {
...
private string _categoryName = "";
private List<Category> _subCategories = new List<Category>();
public string CategoryName { get { return _categoryName; } set { _categoryName = value; } }
public List<Category> SubCategories { get { return _subCategories; } set { _subCategories = value; } }
...
}
I have a method, GetCategories(string parentCategory), that returns all child categoryNames as List. Each radioProgram.Category (yes, name needs to be refactored to plural) is itself a List and may contain zero, one or more categoryNames. I'm getting my master list of radioPrograms and I want to return a subset that contain where each one contains at least one categoryName that matches the set from GetCategories.
I'm trying to avoid changing the architecture of the application (which is a potential solution) as it means a lot of refactoring of existing functionality AND I think this happens to be a good exercise for tackling and understanding LINQ.
One thing you could use is
myclasses
.Where(o => o.category.Any(c => subset.Contains(c)));

A more concise syntax in C# constructor?

I have a constructor something like the following:
using Microsoft.Data.Extensions;
public class Complaint
{
public int Id {get; set;}
public int Transcript {get; set;}
//... etc. ... Lots more properties
public Complaint(int id)
{
var command = dataContext.CreateStoreCommand(
"dbo.stp_Complaint_Get",
CommandType.StoredProcedure,
new SqlParameter("Id", id));
var complaint = command.Materialize(x =>
new Complaint
{
Id = x.Field<int>("Id"),
Transcript = x.Field<string>("Transcript");
//... etc. ... Lots more fields from db
}
this.Id = complaint.Id;
this.Transcript = complaint.Transcript;
//... etc. ... Lots more properties to set
}
}
Is there a syntax in C# that would allow me to carry out the last part in one step instead of two? i.e. conceptually something like this:
this = command.Materialize(x =>
new Complaint
{
Id = x.Field<int>("Id"),
Transcript = x.Field<string>("Transcript");
}
Well, you could use a static method instead of a constructor:
public static Complaint FromId(int id)
{
var command = dataContext.CreateStoreCommand(
"dbo.stp_Complaint_Get",
CommandType.StoredProcedure,
new SqlParameter("Id", id));
return command.Materialize(x =>
new Complaint
{
Id = x.Field<int>("Id"),
Transcript = x.Field<string>("Transcript");
//... etc. ... Lots more fields from db
});
}
Not inherently. You could store the complaint object inside the class, and have all the properties point off that rather than setting them all from the constructor.
eg
public class Complaint
{
private readonly {type of complaint} m_Complaint;
public int Id
{
get { return m_Complaint.Id; }
}
// ...etc
}
You could get more complicated if you don't have a setter on m_Complaint - keeping nullable backing fields, and check that before you access the m_Complaint properties
I believe you may try something like this:
var currentInstance = this;
var complaint = command.Materialize(x =>
new Complaint
{
Id = currentInstance.Id = x.Field("Id"),
Transcript = currentInstance.Transcript = x.Field("Transcript");
//... etc. ... Lots more fields from db
});
I don't think you can capture this in the closure, so using that currentInstance trick should help, however it may as well turn out to be redundant.
Besides, code such as that one is sort of obfuscated compared to your current solution. I believe that your code is pretty fine as it is.
I gather that you're trying to avoid setting all of those properties twice, because any change to the structure requires you to update the properties in two places, is that correct?. You could try to use some reflection to copy the properties from one instance to another.
var complaint = command.Materialize(x =>
new Complaint
{
Id = x.Field<int>("Id"),
Transcript = x.Field<string>("Transcript");
//... etc. ... Lots more fields from db
}
foreach (var prop in typeof(Complaint).GetProperties())
...
Have the complaint object as a member variable and the get/set properties accesses the underlying complaint's properties?

Categories

Resources