Stack overflow on list traversal - c#

I've sourced my data for a treeview using the Proces datastructure below. expanded simply indicates whether or not the tree item has been expanded to show all of its children. This is my attempt to iterate through a map all showing items into a DataTable.
public class Proces
{
public string PN { get; set; }
public string Description { get; set; }
public int Qty { get; set; }
public string PartType { get; set; }
public decimal PricePer { get; set; }
public string Mfr { get; set; }
public int Stock { get; set; }
public int OnOrder { get; set; }
public string parent { get; set; }
public bool expanded { get; set; } = false;
public List<Proces> subProcesses { get; set; }
}
I'm trying to map this out into a DataTable, but i keep getting a stack overflow.
void generateShownTree(List<Proces> proccess)
{
foreach (Proces proc in processes)
{
DataRow drNew = export.NewRow();
drNew["Parent"] = proc.parent;
drNew["PN"] = proc.PN;
drNew["Description"] = proc.Description;
drNew["Qty"] = proc.Qty;
drNew["PartType"] = proc.PartType;
drNew["PricePer"] = proc.PricePer;
drNew["Mfr"] = proc.Mfr;
drNew["Stock"] = proc.Stock;
drNew["OnOrder"] = proc.OnOrder;
export.Rows.Add(drNew);
if (proc.expanded == true)
{
foreach (Proces subProc in proc.subProcesses)
{
subProc.parent = proc.PN;
drNew = export.NewRow();
drNew["Parent"] = subProc.parent;
drNew["PN"] = subProc.PN;
drNew["Description"] = subProc.Description;
drNew["Qty"] = subProc.Qty;
drNew["PartType"] = subProc.PartType;
drNew["PricePer"] = subProc.PricePer;
drNew["Mfr"] = subProc.Mfr;
drNew["Stock"] = subProc.Stock;
drNew["OnOrder"] = subProc.OnOrder;
export.Rows.Add(drNew);
generateShownTree(proc.subProcesses);
}
}
}
}

I assume you don't want to iterate the list of subprocesses as well as invoke the generateShownTree method recursively. I also changed the name of the argument passed to generateShownTree to match the object being iterated.
static void generateShownTree(List<Proces> processes)
{
foreach (Proces proc in processes)
{
DataRow drNew = export.NewRow();
drNew["Parent"] = proc.parent;
drNew["PN"] = proc.PN;
drNew["Description"] = proc.Description;
drNew["Qty"] = proc.Qty;
drNew["PartType"] = proc.PartType;
drNew["PricePer"] = proc.PricePer;
drNew["Mfr"] = proc.Mfr;
drNew["Stock"] = proc.Stock;
drNew["OnOrder"] = proc.OnOrder;
export.Rows.Add(drNew);
if (proc.expanded)
{
generateShownTree(proc.subProcesses);
}
}
}

Related

Initialize object array inside another array c#

I have the following class
public class ResProductSetupData
{
public List<ProductSetup> data { get; set; }
}
public class ProductSetup
{
public List<Fundtype> FundType { get; set; }
}
public class Fundtype
{
public string FundType { get; set; }
public bool IsGIO { get; set; }
public string ReportCode { get; set; }
public List<Fundlist> FundList { get; set; }
}
public class Fundlist
{
public string FundCode { get; set; }
public string FundDesc { get; set; }
public decimal MinAllocation { get; set; }
public string VPMSField { get; set; }
public string FundSpec { get; set; }
}
Now I want to initialize this object inside another file so that I can fill its values. Fundtype is a list and FundList is another list inside FundType.
ProductSetup prodSetup = new ProductSetup();
Fundtype fundType = new Fundtype();
Fundlist fundlist = new Fundlist();
So Inside a foreach loop I instantiated these objects
prodSetup.FundType = new List<Fundtype>();
foreach (var fund in fundTypeData)
{
fundType.FundType = fund.FundType;
fundType.IsGIO = fund.IsGIO;
fundType.ReportCode = "";
prodSetup.FundType.Add(fundType);
var listOfFund = GetProductFund(prodSetup.ProdCode, fund.FundType);
int i = 0;
foreach (var listFundData in listOfFund)
{
var fundDetails = GetFundDetails(listFundData.FundCode);
fundlist.FundCode = listFundData.FundCode;
fundlist.VPMSField = listFundData.VPMSField;
fundlist.FundDesc = fundDetails[0].FundDesc;
fundlist.MinAllocation = fundDetails[0].MinAllocation;
fundlist.FundSpec = fundDetails[0].FundSpec;
prodSetup.FundType[i].FundList.Add(fundlist);
i++;
}
}
When I add data into the Fundlist list, an error will show System.NullReferenceException: 'Object reference not set to an instance of an object.'. I know I have to instantiate first, but I dont know how. Any help would be appreciated.
Update, I have instantiated the FundList array as below
int i = 0;
foreach (var listFundData in listOfFund)
{
prodSetup.FundType[i].FundList = new List<Fundlist>();
var fundDetails = GetFundDetails(listFundData.FundCode);
fundlist.FundCode = listFundData.FundCode;
fundlist.VPMSField = listFundData.VPMSField;
fundlist.FundDesc = fundDetails[0].FundDesc;
fundlist.MinAllocation = fundDetails[0].MinAllocation;
fundlist.FundSpec = fundDetails[0].FundSpec;
prodSetup.FundType[i].FundList.Add(fundlist);
i++;
}
The first index [0] is fine. But when it loops to the second index to instantiate the second index [1], it throws another error Index was out of range. Must be non-negative and less than the size of the collection.\r\nParameter name: index

Something is getting wrong with adding a list to existing List

I'm trying to realize the listBox with List where i getting some variable.
And when i wonna to add a new "Object" to static List i getting a NullReferenceException
This is my code where i adding a new List
if (EventArgsIn.Message.Chat.Id == MainChatId)
{
if (EventArgsIn.Message.ReplyToMessage != null)
{
var _tempMessage = new listBoxMessage()
{
From = EventArgsIn.Message.From.Username,
FromId = EventArgsIn.Message.From.Id,
MessageId = EventArgsIn.Message.MessageId,
MessageText = EventArgsIn.Message.Text,
MessageIdReply = 0
};
tempMessageMain.Add(_tempMessage);
} else
{
var _tempMessage = new listBoxMessage() {
From = EventArgsIn.Message.From.Username,
FromId = EventArgsIn.Message.From.Id,
MessageId = EventArgsIn.Message.MessageId,
MessageText = EventArgsIn.Message.Text,
MessageIdReply = 0
};
tempMessageMain.Add(_tempMessage);
}
}
And here is my static List
public static List<listBoxMessage> tempMessageMain;
A-a-and my class where i doing Template
public class listBoxMessage
{
public listBoxMessage()
{
}
public string From { get; set; }
public int FromId { get; set; }
public int MessageId { get; set; }
public string MessageText { get; set; }
public int MessageIdReply { get; set; }
}
}
This is test code*
You declared a listbox with next line:
public static List<listBoxMessage> tempMessageMain;
The value of tempMessageMain is still null.
Now you have to create a new instance of tempMessageMain:
public static List<listBoxMessage> tempMessageMain = new List<listBoxMessage>();

Tree hierarchy setting flag true if child exists C#

I am trying to set issetting flag to true , if child exists for a
parent.
//Class file
public class EopsModule
{
public int ID { get; set; }
public string ModuleCode { get; set; }
public string Description { get; set; }
public bool IsDefaultModule { get; set; }
public int? ParentID { get; set; }
public bool IsSetting { get; set; }
public List<EopsModule> Children { get; set; }
}
public IResponseResult GetApplicationSettingWithModule()
{
IResponseResult responseResult = new ResponseResult();
dynamic dynamic = new ExpandoObject();
try
{
var settingsDetails = _databaseManager.GetMultipleDataByJson(DatabaseStoredProcedures.spGetAllApplicationSetting.ToString()).Result;
var oObjectDeserializeObject = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(settingsDetails);
//get here all EopsModule in List<EopsModule>
var moduleTreeHierarchy = _eopsModuleManager.GetAllEopsModuleWithHierarchy().Result;
dynamic.settingsDetails = oObjectDeserializeObject;
dynamic.moduleTreeHierarchy = moduleTreeHierarchy;
string oModuleCode = string.Empty;
foreach (var item in oObjectDeserializeObject)
{
oModuleCode = item.moduleCode;
moduleTreeHierarchy.
Where(x => x.ModuleCode == oModuleCode).ToList().ForEach(x =>
{
x.IsSetting = true;
});
}
responseResult = Helper.Response.ResponseModel(dynamic, true, Helper.Constants.ApiSuccess, HttpStatusCode.OK, true);
}
catch (Exception)
{
responseResult = Helper.Response.ResponseModel(null, false, Helper.Constants.ApiFailure, HttpStatusCode.BadRequest, true);
}
return responseResult;
}
The loop i am iterating is working for parent level but , its not updating the value for child values,
wondering if it can be achieved by recursive function.
Please find the output with existing code :
Have you tried something like this? I did not pass it through compiler but you'll get the idea.
public UpdateModuleAndChildren(Module moduleTreeHierarchy) {
if(moduleTreeHierarchy.children != null && moduleTreeHierarchy.children.Count() > 0) {
moduleTreeHierarchy.children.forEach(x => { this.UpdateModuleAndChildren(x) });
module.IsSetting = true;
}
}
Let me know if it helps.
In your code you will just call this.UpdateModuleAndChildren(moduleTreeHierarchy)

How do I create and insert one-to-many object with entity framework c#

I'm trying to create an object and insert to the database but keep getting the same error no matter what I try.
The row that I get the error on is ColumnGroupTest.ValidValues.Add(memberComment1); the error is
error message
NullReferenceException was unhandled by user code
my models
public class StoreColumnName
{
public int Id { get; set; }
public string StoreColumnGroupName { get; set; }
public string ColumnName { get; set; }
public string ColumnType { get; set; }
public List<StoreValidValue> ValidValues { get; set; }
}
public class StoreValidValue
{
public int Id { get; set; }
public string ValidValue { get; set; }
public StoreColumnName StoreColumnName { get; set; }
}
my controller
public ActionResult Index()
{
XDocument document = XDocument.Load(#"C:\Users\Physical.xml");
var result = document.Descendants("ColumnGroup");
foreach(var item in result){
var ColumnGroupName = item.Attribute("name").Value;
var Columns = item.Descendants("Column");
foreach (var itemColumn in Columns)
{
StoreColumnName ColumnGroup = new StoreColumnName();
var ColumnGroupTest = new StoreColumnName
{
StoreColumnGroupName = ColumnGroupName,
ColumnName = itemColumn.Attribute("name").Value,
ColumnType = itemColumn.Attribute("type").Value,
Id = 11
};
var ValidValues = itemColumn.Descendants("ValidValues");
var Values = ValidValues.Descendants("Value");
foreach (var Value in Values)
{
var memberComment1 = new StoreValidValue
{
StoreColumnName = ColumnGroupTest,
ValidValue = Value.Value,
Id = 101
};
ColumnGroupTest.ValidValues.Add(memberComment1);
}
}
}
return View();
}
(I gladly take tips on what I can improve when asking for help/guiding here).
Can anyone help ?
The issue that you're having is that you don't initialize your ValidValues property to a list. By default, those types of properties initialize to null unless you specify differently.
The best approach is to add that initialization to your constructor of that object.
public StoreColumnName() {
this.ValidValues = new List<StoreValidValue>();
}

error when populating list based on class in generic method

I have a list defined as below in each of 11 different classes (which handle web-services)
private List<edbService> genEdbService;
internal class edbService
{
public string ServiceID { get; set; }
public string ServiceName { get; set; }
public string ServiceDescr { get; set; }
public string ServiceInterval { get; set; }
public string ServiceStatus { get; set; }
public string ServiceUrl { get; set; }
public string SourceApplication { get; set; }
public string DestinationApplication { get; set; }
public string Function { get; set; }
public string Version { get; set; }
public string userid { get; set; }
public string credentials { get; set; }
public string orgid { get; set; }
public string orgunit { get; set; }
public string customerid { get; set; }
public string channel { get; set; }
public string ip { get; set; }
}
The list is populated in each class by reading the web-service configuration data from xml files in each class:
public DCSSCustomerCreate_V3_0()
{
try
{
XElement x = XElement.Load(global::EvryCardManagement.Properties.Settings.Default.DataPath + "CustomerCreate.xml");
// Get global settings
IEnumerable<XElement> services = from el in x.Descendants("Service")
select el;
if (services != null)
{
edb_service = new List<edbService>();
// edb_service= Common.populateEDBService("CustomerCreate.xml");
foreach (XElement srv in services)
{
edbService edbSrv = new edbService();
edbSrv.ServiceID = srv.Element("ServiceID").Value;
edbSrv.ServiceName = srv.Element("ServiceName").Value;
edbSrv.ServiceDescr = srv.Element("ServiceDescr").Value;
edbSrv.ServiceInterval = srv.Element("ServiceInterval").Value;
edbSrv.ServiceStatus = srv.Element("ServiceStatus").Value;
edbSrv.ServiceUrl = srv.Element("ServiceUrl").Value;
foreach (XElement ServiceHeader in srv.Elements("ServiceHeader"))
{
...
now what I want to do is have this code in one place in my Common.cs class so I tried:
public static List<edbService> populateEDBService(string xmlDataFile)
{
try
{
XElement x = XElement.Load(global::EvryCardManagement.Properties.Settings.Default.DataPath + xmlDataFile);
// Get global settings
IEnumerable<XElement> services = from el in x.Descendants("Service")
select el;
if (services != null)
{
//edb_Service = new List<edbService>();
foreach (XElement srv in services)
{
edbService edbSrv = new edbService();
edbSrv.ServiceID = srv.Element("ServiceID").Value;
edbSrv.ServiceName = srv.Element("ServiceName").Value;
edbSrv.ServiceDescr = srv.Element("ServiceDescr").Value;
edbSrv.ServiceInterval = srv.Element("ServiceInterval").Value;
edbSrv.ServiceStatus = srv.Element("ServiceStatus").Value;
edbSrv.ServiceUrl = srv.Element("ServiceUrl").Value;
foreach (XElement ServiceHeader in srv.Elements("ServiceHeader"))
{
edbSrv.SourceApplication = ServiceHeader.Element("SourceApplication").Value;
edbSrv.DestinationApplication = ServiceHeader.Element("DestinationApplication").Value;
edbSrv.Function = ServiceHeader.Element("Function").Value;
edbSrv.Version = ServiceHeader.Element("Version").Value;
foreach (XElement ClientContext in ServiceHeader.Elements("ClientContext"))
{
edbSrv.userid = ClientContext.Element("userid").Value;
edbSrv.credentials = ClientContext.Element("credentials").Value;
edbSrv.orgid = ClientContext.Element("orgid").Value;
edbSrv.orgunit = ClientContext.Element("orgunit").Value;
edbSrv.customerid = ClientContext.Element("customerid").Value;
edbSrv.channel = ClientContext.Element("channel").Value;
edbSrv.ip = ClientContext.Element("ip").Value;
}
}
// populateEDBService.Add(edbSrv);
}
}
}
catch (Exception ex)
{
/* Write to log */
Common.logBuilder("CustomerCreate : Form --> CustomerCreate <--", "Exception", Common.ActiveMQ,
ex.Message, "Exception");
/* Send email to support */
emailer.exceptionEmail(ex);
}
return;
}
Now I get a compile error on the return; saying that An object of a type convertible to 'System.Collections.Generic.List<EvryCardManagement.Common.edbService>' is required
and in the class that should call this method, I want to do something like:
edb_service = Common.populateEDBService("CustomerUpdate.xml");
but I get an error Cannot implicitly convert type 'System.Collections.Generic.List<EvryCardManagement.Common.edbService>' to 'System.Collections.Generic.List<EvryCardManagement.CustomerUpdate.edbService>'
So firstly how should I return the list from my generic method and how should I call it to return the list populated with the configuration data?
It sounds like you have your class edbService defined in two namespaces,
EvryCardManagement.Common and
EvryCardManagement.CustomerUpdate
I would suggest defining it in only EvryCardManagement.Common and have everything reference it from there.

Categories