i have added multiple values to an array using 3 different classes that i have created when i use the foreach loop i only get the values from the first class is there any way to use foreach on multiple classes?
AdvertDao advert = new AdvertDao();
var array = new ArrayList();
array = advert.fillAdvert();
foreach (Member m in array)
{
txtBoxEmail.Text = m.Email;
txtBoxPhone.Text = m.Phone.ToString();
txtBoxUsername.Text = m.Username;
}
foreach (Consoles c in array)
{
cmbConsole.Text = c.ConsoleName;
}
foreach (Advert a in array)
{
cmbGenre.Text = a.Genre;
lblDateStarted.Text = a.Date.ToString("dd/MM/yyyy");
txtBoxPrice.Text = a.Price.ToString();
txtBoxName.Text = a.Name;
txtBoxDesc.Text = a.Description;
}
fillAdvert() method:
public ArrayList fillAdvert()
{
Member member = new Member();
Advert advert = new Advert();
Consoles console = new Consoles();
Picture picture = new Picture();
ArrayList advertList = new ArrayList();
if (!DatabaseConnection.IsOpen)
{
DatabaseConnection.Open();
}
OracleCommand cmd = new OracleCommand();
cmd.Connection = DatabaseConnection.Connection;
string str = "SELECT * FROM ADVERT_ADPIC_MEMBER_CONSOLE WHERE username = '" + GlobalVariables.Username + "' AND name = '" + GlobalVariables.SellingName + "'";
cmd.CommandText = str;
OracleDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
member.Username = dr.GetString(0);
member.MemberID = dr.GetInt32(1);
member.Phone = dr.GetInt32(2);
member.Email = dr.GetString(3);
console.ConsoleName = dr.GetString(5);
advert.Description = dr.GetString(6);
advert.Genre = dr.GetString(7);
advert.Date = dr.GetDateTime(8);
advert.Price = dr.GetDouble(9);
advert.Name = dr.GetString(4);
advertList.Add(member);
advertList.Add(console);
advertList.Add(advert);
}
return advertList;
}
could be an easier way but its the way they want it done in the college.
You can use one foreach block with object as the element type, but you need to check the type of the element, convert the element to the correct type, and implement the logic according to the type of the element.
foreach (object obj in array)
{
if (obj is Member)
{
Member m = (Member)obj;
txtBoxEmail.Text = m.Email;
txtBoxPhone.Text = m.Phone.ToString();
txtBoxUsername.Text = m.Username;
}
else if (obj is Consoles)
{
Consoles c = (Consoles)obj;
cmbConsole.Text = c.ConsoleName;
}
else if (obj is Advert)
{
Advert a = (Advert)obj;
cmbGenre.Text = a.Genre;
lblDateStarted.Text = a.Date.ToString("dd/MM/yyyy");
txtBoxPrice.Text = a.Price.ToString();
txtBoxName.Text = a.Name;
txtBoxDesc.Text = a.Description;
}
}
The foreach looping requires that the object implements the System.Collections.IEnumerable or System.Collections.Generic.IEnumerable interface.
So, the answer is "no"
There isn't a direct way to use more than ONE object in a foreach looping.
One way to do what you want is with interfaces and a foreach looping, if you make your three classes implement the same Interface. ex:
public interface IInterface
{
string Text { get; }
}
Then, if you implement this interface in every class, you can do something like this:
foreach (IInterface i in array)
{
//do whatever you want with the text here.
}
But you will be able to use only the properties you implement in the interface.
SO if you need "different" properties depending on the object, you will have to use some kind of indicator of type and use if's or switchs inside the looping, besides having to implement all the required properties in the interface.
Related
I have read some threads that seem to be similar to this but can't find the fix for my issue, I've not used stack overflow much so pls bear with me
I have a while loop using an SqlDataReader which is pulling information from a DB and putting it into a List for Development Requests as below
public ListOfDevelopmentRequestsModel GetDevRequests(List<SelectListItem> evaluators)
{
SqlCommand cmd = new SqlCommand(StoredProcedures.DevRequests.GetDevRequests, Conn);
cmd.CommandType = CommandType.StoredProcedure;
ListOfDevelopmentRequestsModel ListOfDevRequests = new ListOfDevelopmentRequestsModel();
Conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
DateTime requestDate = Convert.ToDateTime(reader["DateCreated"].ToString());
string requestorFirstName = reader["Staff First Name"].ToString();
string requestorLastName = reader["Staff Last Name"].ToString();
string requestorEmailAddress = reader["Staff Email"].ToString();
string solutionName = reader["SolutionName"].ToString();
string solutionDescription = reader["SoultionDescription"].ToString();
string solutionElementName = reader["SolutionElementName"].ToString();
string solutionElementDescription = reader["SolutionElementDescription"].ToString();
string itemToChange = reader["ItemChange"].ToString();
string changeDetails = reader["ChangeDetail"].ToString();
List<SelectListItem> evaluatorList = new List<SelectListItem>(DisplayCurrentEvaluator(evaluators, evaluator));
DevelopmentRequestModel DevRequest = new DevelopmentRequestModel
{
RequestDate = requestDate,
RequestorName = $"{requestorFirstName} {requestorLastName}",
RequestorEmailAddress = requestorEmailAddress,
SolutionName = solutionName,
SolutionDescription = solutionDescription,
SolutionElementName = solutionElementName,
SolutionElementDescription = solutionElementDescription,
ItemToChange = itemToChange,
ChangeDetails = changeDetails,
AccordionHeading = $"{(changeID.PadLeft(4, '0'))} - {requestorFirstName} {requestorLastName} - {itemToChange}"
};
ListOfDevRequests.DevelopmentRequests.Add(DevRequest);
}
Conn.Close();
return ListOfDevRequests;
}
I also have a List for getting Evaluators of the requests
public static List<SelectListItem> GetEvaluators()
{
List<SelectListItem> evaluators = new List<SelectListItem>();
SqlCommand cmd = new SqlCommand(StoredProcedures.DevRequests.GetEvaluators, Conn);
cmd.CommandType = CommandType.StoredProcedure;
Conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
evaluators.Add(
new SelectListItem
{
Text = reader["Staff Name"].ToString(),
Value = reader["Staff Code"].ToString(),
});
}
Conn.Close();
return evaluators;
}
Finally I have a List that will pass the above Evaluators List in and the Evaluator that was pulled from the DB: string evaluator = reader["Evaluator"].ToString(); and will set the default value of the select list based on whether the Evaluator name matches the Text value, and set it as the selected select list item.
public List<SelectListItem> DisplayCurrentEvaluator(List<SelectListItem> evaluators, string evaluator)
{
foreach (var item in evaluators)
{
if (item.Text == evaluator)
{
item.Selected = true;
}
else
{
item.Selected = false;
}
}
return evaluators;
}
The issue is that the first item in the loop has the Evaluator "Bill" and "Bill" is selected, and works fine, however the second item in the loop is "John", and when it sets "John" to selected, it replaces "Bill" as the selected value in the first item with "John"
The code has ended up a mess as I have tried multiple different ways to fix but I'm stumped and would appreciate help.
Sorry if the post is formatted poorly to read, I can try to reformat and provide more information if requested.
Cheers
EDITED CODE:
GetDevRequests()
public ListOfDevelopmentRequestsModel GetDevRequests(List<SelectListItem> evaluators)
{
SqlCommand cmd = new SqlCommand(StoredProcedures.DevRequests.GetDevRequests, Conn);
cmd.CommandType = CommandType.StoredProcedure;
ListOfDevelopmentRequestsModel ListOfDevRequests = new ListOfDevelopmentRequestsModel();
Conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
List<SelectListItem> evaluatorList = new List<SelectListItem>();
while (reader.Read())
{
string changeID = reader["ChangeID"].ToString();
string evaluator = reader["Evaluator"].ToString();
string status = reader["Status"].ToString();
string priority = reader["Priority"].ToString();
string eliteID = reader["RequestorID"].ToString();
DateTime requestDate = Convert.ToDateTime(reader["DateCreated"].ToString());
string requestorFirstName = reader["Staff First Name"].ToString();
string requestorLastName = reader["Staff Last Name"].ToString();
string requestorEmailAddress = reader["Staff Email"].ToString();
string solutionName = reader["SolutionName"].ToString();
string solutionDescription = reader["SoultionDescription"].ToString();
string solutionElementName = reader["SolutionElementName"].ToString();
string solutionElementDescription = reader["SolutionElementDescription"].ToString();
string itemToChange = reader["ItemChange"].ToString();
string changeDetails = reader["ChangeDetail"].ToString();
evaluatorList = DisplayCurrentEvaluator(evaluators, evaluator);
DevelopmentRequestModel DevRequest = new DevelopmentRequestModel
{
ChangeID = (changeID.PadLeft(4, '0')),
Evaluator = evaluator,
Evaluators = evaluatorList,
Status = status,
Priority = priority,
EliteID = eliteID,
RequestDate = requestDate,
RequestorName = $"{requestorFirstName} {requestorLastName}",
RequestorEmailAddress = requestorEmailAddress,
SolutionName = solutionName,
SolutionDescription = solutionDescription,
SolutionElementName = solutionElementName,
SolutionElementDescription = solutionElementDescription,
ItemToChange = itemToChange,
ChangeDetails = changeDetails,
AccordionHeading = $"{(changeID.PadLeft(4, '0'))} - {requestorFirstName} {requestorLastName} - {itemToChange}"
};
ListOfDevRequests.DevelopmentRequests.Add(DevRequest);
}
Conn.Close();
return ListOfDevRequests;
}
DisplayCurrentEvaluator()
public List<SelectListItem> DisplayCurrentEvaluator(List<SelectListItem> selectListItems, string selectListDefaultItem)
{
foreach (var item in selectListItems)
{
item.Selected = item.Text == selectListDefaultItem;
}
return selectListItems;
}
The problem is in this line:
List<SelectListItem> evaluatorList = new List<SelectListItem>(DisplayCurrentEvaluator(evaluators, evaluator));
First, this can also be written as
List<SelectListItem> evaluatorList = DisplayCurrentEvaluator(evaluators, evaluator);
Your DisplayCurrentEvaluator already returns a correct list, so there is no need to copy it into a new one.
But this is a minor point as you don't use that evaluatorList as far as I can see. In every iteration of that while-loop you are creating a new one (which probably isn't what you want) and then you forget about it. I also don't see where evaluator is set, but that is probably in code you didn't show.
So you will need to generate this list once, outside the loop and keep it (probably in a class-level field or property).
And an extra tip, that DisplayCurrentEvaluator method can also be written as
public List<SelectListItem> DisplayCurrentEvaluator(List<SelectListItem> evaluators, string evaluator)
{
foreach (var item in evaluators)
{
item.Selected = item.Text == evaluator;
}
return evaluators;
}
EDIT after code was shown that set evaluator and used the resulting evaluatorList
Your DisplayCurrentEvaluator updates the original evaluators list and returns it. This effectively results in every evaluatorList pointing to the same list, where the last update wins. So make sure you return a new list.
public List<SelectListItem> DisplayCurrentEvaluator(List<SelectListItem> evaluators, string evaluator)
{
var result = new List<SelectListItem>(evaluators.Count);
foreach (var item in evaluators)
{
result.Add(new SelectListItem { Text = item.Text, Value = item.Value, Selected= item.Text == evaluator};
}
return result;
}
Additionally, declare the evaluatorList (only) inside of the loop.
var evaluatorList = DisplayCurrentEvaluator(evaluators, evaluator);
i need to build a list in a function, then return it to a another list variable
the problem is: inside the function the list is built properly but when i return it to the outer variable it seems like all the elements of the outer list are all similar to the last one added to it inside the function. what is the reason of this?
this is my code:
List<stu> fillObject(SqlDataReader rd)
{
List<stu> stList = new List<stu>();
stu stObj = new stu();
while (rd.Read())
{
stObj.username = rd["username"].ToString();
stObj.password = rd["password"].ToString();
stObj.fname = rd["fname"].ToString();
stObj.lname = rd["lname"].ToString();
stObj.faculty = rd["faculty"].ToString();
stList.Add(stObj);
}
return stList;
}
here is the call of the function:
var friendsList = fillObject(rd);
so looping though 'friendList' would give the same last object added in the builder function.
Try this
List<stu> fillObject(SqlDataReader rd)
{
List<stu> stList = new List<stu>();
while (rd.Read())
{
stu stObj = new stu();
stObj.username = rd["username"].ToString();
stObj.password = rd["password"].ToString();
stObj.fname = rd["fname"].ToString();
stObj.lname = rd["lname"].ToString();
stObj.faculty = rd["faculty"].ToString();
stList.Add(stObj);
}
return stList;
}
what you were missing is initializing stu inside while, due to which there was only one stu object that is being added again and again into stList.
You need to create New STU object inside the loop, Otherwise you keep changing the same referenced object.
Try This :
List<stu> fillObject(SqlDataReader rd)
{
List<stu> stList = new List<stu>();
//stu stObj = new stu();
while (rd.Read())
{
stList.Add(new stu
{
username = rd["username"].ToString(),
password = rd["password"].ToString(),
fname = rd["fname"].ToString(),
lname = rd["lname"].ToString(),
faculty = rd["faculty"].ToString()
});
}
return stList;
}
private void getRRvalue(string DELRRNO)
{
try {
DBSFCDataContext SFC = new DBSFCDataContext();
var query = (from i in SFC.POP10500s where i.POPRCTNM == DELRRNO select new { PONO = i.PONUMBER, DATEREC = i.DATERECD, VENDID = i.VENDORID, ITEMCODE = i.ITEMNMBR, QTYBAGS = i.QTYBAGS, QTYSHIP = i.QTYSHPPD, DEPT = i.TRXLOCTN });
foreach (var r in query)
{
string[] row = {
DELRRNO,
r.PONO,
Convert.ToDateTime(r.DATEREC).ToString(),
r.VENDID,
r.ITEMCODE,
r.QTYBAGS.ToString(),
r.QTYSHIP.ToString(),
r.DEPT
};
//glbVariables.getRRNO = ;
//glbVariables.getPONO = ;
//glbVariables.getRRdateRec = ;
//glbVariables.getVendID = ;
//glbVariables.getItemNO = ;
//glbVariables.getQtyBags = ;
//glbVariables.getQtyShipped = ;
//glbVariables.getLocnCode = ;
}
SFC.Connection.Close();
}
catch (Exception ex)
{ MessageBox.Show(ex.Message.ToString()); }
}
I'm new to C#.NET and I was just thinking if I could use a dynamic array like for this code above do I need to declare a global array like this --> "public static string[] row;" so I can use this array string in another form by calling it with the data that I have stored from this function, could this happen in c#?
I need help here please anyone that is good at arrays in c#...
To get you desired results, you will have to do little more work. I explain your solution using List.
First create a class for your one query result:
public class OneRowData
{
public string DELRRNO;
public string PONO;
public string DATEREC;
public string VENDID;
public string ITEMCODE;
public string QTYBAGS;
public string QTYSHIP;
public string DEPT;
}
In your given code, create a List of OneRowData type and make it public static to access it from outside the class as well:
public static List<OneRowData> QueryResults = new List<OneRowData>();
Now in your foreach loop, create an object of OneRowData, assing values to it and add it to the List:
foreach (var r in query)
{
OneRowData Obj = new OneRowData();
//assing values to them
Obj.DATEREC = Convert.ToDateTime(r.DATEREC).ToString();
Obj.DELRRNO = DELRRNO;
Obj.DEPT = r.DEPT;
Obj.ITEMCODE = r.ITEMCODE;
Obj.PONO = r.PONO;
Obj.QTYBAGS = r.QTYBAGS.ToString();
Obj.QTYSHIP = r.QTYSHIP.ToString();
Obj.VENDID = r.VENDID;
//then add the object to your list
QueryResults.Add(Obj);
}
Now you can simply call your List any where and fetch your data like this:
foreach (OneRowData Row in QueryResults)
{
//Row.DATEREC
//Row.DELRRNO
//call them like this and use as you need
}
These are the two Methods am having a problem with
I want to return both object of csVehicle and csDistributor
as you my code below only returns csVehicle
please help
public List<csVehicle> get_All_Vehicles()
{
var objv = new List<csVehicle>();
IDataReader dr = null;
var objdal = new csDAL();
dr = objdal.executespreturndr("sp_Get_All_Distributor");
while (dr.Read())
{
var d = new csDistributor(); // I put this here so that I can use the propDistrbutorId
var v = new csVehicle();
populate_Data(dr, d,v);
objv.Add(v); //It only adds object of csVehicles and csDistributor is not added
}
return objv; // csDistributor is not returned
}
the populate_Date methods adds data to the two objects csDistributor and csVehicle
private void populate_Data(IDataReader dr, csDistributor d, csVehicle v)
{
v._vehicleRegNo = dr["VehicleRegNo"].ToString();
d.propDistrbutorId = Convert.ToInt32(dr["DistrbutorId"]);
}
Here's a simple solution:
public List<object> get_All_Vehicles()
{
var objv = new List<object>();
IDataReader dr = null;
var objdal = new csDAL();
dr = objdal.executespreturndr("sp_Get_All_Distributor");
while (dr.Read())
{
var d = new csDistributor();
var v = new csVehicle();
populate_Data(dr, d,v);
objv.Add(v);
objv.Add(d);
}
return objv;
}
A more sophisticated solution would be to define a parent class from which both csDistributor and csVehicle inherit, and then return a List<> of that specific type.
Or use an ArrayList, which is just an untyped collection of objects.
Edit: I'm sort of having to guess how your code is being used elsewhere, but try this:
public void get_All_Vehicles(out csVehicle vehicle, out csDistributor distributor)
{
vehicle = new List<csVehicle>();
distributor = new List<csDistributor>();
IDataReader dr = null;
var objdal = new csDAL();
dr = objdal.executespreturndr("sp_Get_All_Distributor");
while (dr.Read())
{
var d = new csDistributor();
var v = new csVehicle();
populate_Data(dr, d,v);
vehicle.Add(v);
distributor.Add(d);
}
}
I have created an asp.net application using Entity Framework. In this I want to add the records into a list. For this I have to use the foreach loop but it always adding only last record data for all records, meaning it's showing same data. Here I have pasted my code. Please verify it once and guide where I can change.
public List<CategoryItems> ListMenuCategory(int MenuId)
{
string str = string.Empty;
string strJSON = string.Empty;
List<CategoryItems> resultmenu;
resultmenu = new List<CategoryItems>();
List<CategoryItems> Result;
Result = new List<CategoryItems>();
bool check = true;
var objmenuCategory = from cat in objEntity.menucategories where cat.MenuId == MenuId && cat.Active == check select cat;
CategoryItems Categorylist = new CategoryItems();
foreach (menucategory category in objmenuCategory)
{
Categorylist.CategoryName = category.CategoryName;
Categorylist.Description = category.Description;
int menuid = category.MenuCategoryId;
List<menuitem> menuitems = GetMenucategories(menuid);
foreach (var items in menuitems)
{
Categorylist.ItemName = items.ItemName;
Categorylist.Description = items.Description;
Categorylist.Price = (float)items.Price;
string Image = items.Picture;
Categorylist.Picture = "http://restaurantmanager.testshell.net/Images/" + Image;
Categorylist.Thumbnail = "http://restaurantmanager.testshell.net/Images/" + items.Thumbnail;
if (items.CreatedDate != null)
{
Categorylist.CreatedDate = (DateTime)items.CreatedDate;
}
if (items.ModifiedDate != null)
{
Categorylist.ModifiedDate = (DateTime)items.ModifiedDate;
}
Result.Add(Categorylist);
}
// Result.AddRange(menus);
}
return Result;
}
private List<menuitem> GetMenucategories(int p)
{
restaurantEntities objEntity1 = new restaurantEntities();
var menuitems = from items in objEntity1.menuitems where items.MenuCategoryId == p select items;
return menuitems.ToList();
}
You are creating the Categorylist item outside of the loops, so you are only using one single item, filling it with different data and adding it over and over to the result.
You have to create the item inside the innermost loop, so that each iteration gets its own object.
Note: ChrisF also spotted that you call AddRange inside the loop, which has the result that you will add the same set of items over and over. You don't need to call AddRange at all, you can just skip the Result list entirely and just return resultmenu instead.