Updating child items in List updates all Items in C# - c#

Here are my list :
public class PayRateDaysModel
{
public string day_name { get; set; }
public List<RateList> multiplier { get; set; }
}
public class RateList
{
public double start_after { get; set; }
public double rate_multiplier { get; set; }
}
when I'm trying to update any value in multiplier of PayRateDaysModel then its updating all multiplier values of PayRateDaysModel. Iw ant to update only current item. Below is my code :
var dayExists = daysModel.Where(x => x.day_name == day_name).FirstOrDefault();
if(dayExists==null)
{
PayRateDaysModel days = new PayRateDaysModel();
days.day_name = day_name;
days.multiplier = rate_list;
daysModel.Add(days);
}
else
{
//update
dayExists.day_name = "abc";
dayExists.multiplier.FirstOrDefault().rate_multiplier = 1;
}

Based on what you have shown to us I would think that you are creating the rate_list somewhere above like rate_list = new RateList(…) and you are setting this to all of your days in days.multiplier = rate_list;. Since you did not recreate that rate_list for every element, any time you change it in one of your dayExists you will change it for all the others as well.
So you should do something like this days.multiplier = new RateList(…);

Related

How to pass a value from within a List up to a method? MessagingCenter?

I have created a List object for charting in SyncFusion. I have performed a calculation at the end of the List creation that gets the Minimum value of one of the objects in the List (which is 'close'), and ascribes it to a variable called 'AxisMinimum'. That works fine.
I now need to take that variable's value and pass it up into another method that can then use it and make an adjustment to the chart. That method is called 'NumbericalAxis_ActualRangeChanged'.
Trying to use AxisMinimum in the 'NumbericalAxis_ActualRangeChanged' method generates an error as it doesn't exist in the current context. Would using a Messaging.Center approach be appropriate or is there a better way?
[DesignTimeVisible(false)]
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
private void NumericalAxis_ActualRangeChanged(object sender, ActualRangeChangedEventArgs e)
{
e.ActualMinimum = AxisMinimum;
}
}
public class SaleInfo
{
public string date { get; set; }
public string minute { get; set; }
public string label { get; set; }
public double high { get; set; }
public double low { get; set; }
public double open { get; set; }
public double close { get; set; }
public double average { get; set; }
public int volume { get; set; }
public double notional { get; set; }
public int numberOfTrades { get; set; }
}
public class SalesViewModel
{
public List<SaleInfo> SalesData { get; set; }
public SalesViewModel()
{
SalesData = new List<SaleInfo>();
SalesData.Add(new SaleInfo { date = "2019-08-16", minute = "09:30", label = "09:30 AM", high = 204.84, low = 204.05, open = 204.3, close = 904.75, average = 204.508, volume = 8709, notional = 1781061.51, numberOfTrades = 69 });
SalesData.Add(new SaleInfo { date = "2019-08-16", minute = "09:31", label = "09:31 AM", high = 204.8, low = 204.46, open = 204.8, close = 904.5, average = 204.622, volume = 5783, notional = 1183329.75, numberOfTrades = 58 });
SalesData.Add(new SaleInfo { date = "2019-08-16", minute = "09:32", label = "09:32 AM", high = 204.72, low = 204.34, open = 204.46, close = 904.36, average = 204.548, volume = 4468, notional = 913920.6, numberOfTrades = 50 });
SalesData.Add(new SaleInfo { date = "2019-08-16", minute = "09:33", label = "09:33 AM", high = 204.41, low = 204.06, open = 204.39, close = 904.06, average = 204.243, volume = 1834, notional = 374581.99, numberOfTrades = 22 });
double AxisMinimum = SalesData.Min(SaleInfo => SaleInfo.close);
}
}
Thanks Çöđěxěŕ, that did the trick. Using the following code made it work...
public void NumericalAxis_ActualRangeChanged(object sender, ActualRangeChangedEventArgs e)
{
SalesViewModel p = new SalesViewModel();
e.ActualMinimum = p.AxisMinimum;
}
By creating an instance of SalesViewModel object I could then get at that variable and use it. Thanks.
In the above solution, doesn't provide you with the correct value of AxisMinium (min value of Close property values in SaleInfo). Because each time, you are creating a new instance of SalesViewModel.
SalesViewModel p = new SalesViewModel();
It has been modified by
public void NumericalAxis_ActualRangeChanged(object sender,ActualRangeChangedEventArgs e){
SalesViewModel p = (sender as Axis).BindingContext as SalesViewModel;
if(p != null )
{
e.ActualMinimum = p.AxisMinimum;
}}

List sorting troubles

I have a list of programmers:
programmers.Add(new Programmer("Jake", 1.9, 2000));
programmers.Add(new Programmer("Richard", 1.0, 1300));
and I need to create a new list of sorted programmers by this
value => 2000 / 1.9.(upward)
I can't figure out how to divide int by double and sort the programmers by this result. Can you please help me how to do so?
So far I've tried:
var ProgrammersSorted = programmers.OrderBy((x,y) => x.DailyWage / y.Speed).ToList();
Programmer class:
public class Programmer
{
public string Name { get; private set; }
public double Speed { get; private set; }
public int DailyWage { get; private set; }
public Project Project { get; private set; }
public string ProjectName
{
get
{
return Project?.Name ?? "No project assigned";
}
}
public Programmer(string name, double speed, int dailyWage)
{
Name = name;
Speed = speed;
DailyWage = dailyWage;
}
}
You are very close. Try this out:
var programmersSorted = programmers.OrderBy(x => x.DailyWage / x.Speed).ToList();
Please try below code, I think this will solve your issue.
var programmers = new List<Programmer>
{
new Programmer("SS",12.3,2345),
new Programmer("ADE",1.21,22345),
new Programmer("AR",12.2,23445),
new Programmer("NK",12.5,23455)
};
var progrmrs = programmers.OrderBy(t => t.DailyWage / t.Speed).ToList();
Console.WriteLine("Name\t Speed\t DailyWage");
foreach (var prgrm in progrmrs)
{
Console.WriteLine("{0}\t {1}\t {2}", prgrm.Name, prgrm.Speed, prgrm.DailyWage);
}

Casting List Type at Runtime C# Reflection

I've been working on using reflection but its very new to me still. So the line below works. It returns a list of DataBlockOne
var endResult =(List<DataBlockOne>)allData.GetType()
.GetProperty("One")
.GetValue(allData);
But I don't know myType until run time. So my thoughts were the below code to get the type from the object returned and cast that type as a list of DataBlockOne.
List<DataBlockOne> one = new List<DataBlockOne>();
one.Add(new DataBlockOne { id = 1 });
List<DataBlockTwo> two = new List<DataBlockTwo>();
two.Add(new DataBlockTwo { id = 2 });
AllData allData = new AllData
{
One = one,
Two = two
};
var result = allData.GetType().GetProperty("One").GetValue(allData);
Type thisType = result.GetType().GetGenericArguments().Single();
Note I don't know the list type below. I just used DataBlockOne as an example
var endResult =(List<DataBlockOne>)allData.GetType() // this could be List<DataBlockTwo> as well as List<DataBlockOne>
.GetProperty("One")
.GetValue(allData);
I need to cast so I can search the list later (this will error if you don't cast the returned object)
if (endResult.Count > 0)
{
var search = endResult.Where(whereExpression);
}
I'm confusing the class Type and the type used in list. Can someone point me in the right direction to get a type at run time and set that as my type for a list?
Class definition:
public class AllData
{
public List<DataBlockOne> One { get; set; }
public List<DataBlockTwo> Two { get; set; }
}
public class DataBlockOne
{
public int id { get; set; }
}
public class DataBlockTwo
{
public int id { get; set; }
}
You might need something like this:
var endResult = Convert.ChangeType(allData.GetType().GetProperty("One").GetValue(allData), allData.GetType());
Just guessing, didn't work in C# since 2013, please don't shoot :)
You probably want something like this:
static void Main(string[] args)
{
var one = new List<DataBlockBase>();
one.Add(new DataBlockOne { Id = 1, CustomPropertyDataBlockOne = 314 });
var two = new List<DataBlockBase>();
two.Add(new DataBlockTwo { Id = 2, CustomPropertyDatablockTwo = long.MaxValue });
AllData allData = new AllData
{
One = one,
Two = two
};
#region Access Base Class Properties
var result = (DataBlockBase)allData.GetType().GetProperty("One").GetValue(allData);
var oneId = result.Id;
#endregion
#region Switch Into Custom Class Properties
if (result is DataBlockTwo)
{
var thisId = result.Id;
var thisCustomPropertyTwo = ((DataBlockTwo)result).CustomPropertyDatablockTwo;
}
if (result is DataBlockOne)
{
var thisId = result.Id;
var thisCustomPropertyOne = ((DataBlockOne)result).CustomPropertyDataBlockOne;
}
#endregion
Console.Read();
}
public class AllData
{
public List<DataBlockBase> One { get; set; }
public List<DataBlockBase> Two { get; set; }
}
public class DataBlockOne : DataBlockBase
{
public int CustomPropertyDataBlockOne { get; set; }
}
public class DataBlockTwo : DataBlockBase
{
public long CustomPropertyDatablockTwo { get; set; }
}
public abstract class DataBlockBase
{
public int Id { get; set; }
}

How to have multiple lists in an Entity of the same type?

I have an entity that needs to have multiple lists of another entity. Each of these lists will be comprised of the same type of entity however, and this seems to confuse the framework. I've read this question:
Multiple collections of same type in entity framework
and followed the suggestion of differentiating the different lists by inheriting different types for each of the lists of items. This does not seem to do anything though.
The error I get is:
Exception:Thrown: "Invalid column name 'ApprovalStage_Id1'.
Invalid column name 'ApprovalStage_Id2'.
Invalid column name 'ApprovalStage_Id3'." (System.Data.SqlClient.SqlException)
A System.Data.SqlClient.SqlException was thrown: "Invalid column name 'ApprovalStage_Id1'.
Invalid column name 'ApprovalStage_Id2'.
Invalid column name 'ApprovalStage_Id3'."
Time: 2/9/2015 3:22:05 PM
Thread:Worker Thread[11116]
And here are my entities. It's a bit dense, but basically the main object is ComplexApprovalProcess, which has some number of ApprovalStages in a single list (that's all fine). The problem comes in with the fact that each ApprovalStage has three lists of Approver, 'Approvers', 'Viewers', and 'Advisors'. When Entity tries to save these entities it throws the error above. Like I said, I tried differentiating these by inheriting three other classes from Approver, so as you can see they are now collections of ReqApprover, Advisor and Viewer, but it still throws the error above just like it did before. Any ideas why Entity is getting confused on this? Each Approver entity should just have a reference back to the ApprovalStage it belongs to, but Entity seems to think it should be referencing three different ApprovalStages and tries to dynamically find those columns, which don't exist. Thanks.
The Entities:
public class ComplexApprovalProcess
{
[Key]
public long Id { get; set; }
[InverseProperty("ApprovalProcessId")]
public List<ApprovalStage> Stages { get; set; }
[ForeignKey("Form")]
public long FormId { get; set; }
public int CurrentStage { get; set; }
public FormBase Form { get; set; }
bool Approved { get; set; }
bool Denied { get; set; }
private bool CheckCompleted() {
foreach (ApprovalStage stage in this.Stages)
{
if (stage.Completed == false)
{
//if any stage is incomplete, the process is not complete
return false;
}
}
//no stages incomplete means all stages complete
return true;
}
private bool AdvanceStage()
{
//check the completion condition of the current stage, if completed, advance to next stage
ApprovalStage current = Stages.Where(m => m.StageOrder == this.CurrentStage).FirstOrDefault();
if (current != null)
{
//check if stage is completed
if (current.CheckCompletion())
{
//check if stage is approved
if (current.Approved)
{
//check if process contains additional stages
if (this.Stages.Count > this.CurrentStage)
{
//Move to next stage
this.CurrentStage += 1;
ApprovalStage next = Stages.Where(m => m.StageOrder == this.CurrentStage).FirstOrDefault();
if (next != null)
{
next.StartStage();
}
else
{
throw new Exception("Huh?");
}
}
}
}
}
else
{
throw new Exception("Wut");
}
return false;
}
public static ComplexApprovalProcess CreateCheckRequestApprovalProcess(FormBase form)
{
UsersModel user = null;
ComplexApprovalProcess process = new ComplexApprovalProcess();
using (TechnologyProjectPlanContext db = new TechnologyProjectPlanContext())
{
int id = SessionVar.Get<int>(SessionVar.USERID);
user = db.UsersModels.Where(m => m.Id == id).FirstOrDefault();
}
process.Form = form;
ApprovalStage InitialReview = new ApprovalStage();
InitialReview.StageOrder = 1;
InitialReview.Approvers = new List<ReqApprover>();
InitialReview.Advisors = new List<Advisor>();
InitialReview.Viewers = new List<Viewer>();
InitialReview.Form = form;
InitialReview.ApprovalProcess = process;
InitialReview.Approvers.Add(new ReqApprover(user, form, InitialReview));
InitialReview.Advisors.Add(new Advisor(user, form, InitialReview));
InitialReview.Viewers.Add(new Viewer(user, form, InitialReview));
InitialReview.StageName = "Initial Review";
ApprovalStage MiddleApproval = new ApprovalStage();
MiddleApproval.StageOrder = 2;
MiddleApproval.Approvers = new List<ReqApprover>();
MiddleApproval.Advisors = new List<Advisor>();
MiddleApproval.Viewers = new List<Viewer>();
MiddleApproval.Form = form;
MiddleApproval.ApprovalProcess = process;
MiddleApproval.Approvers.Add(new ReqApprover(user, form, MiddleApproval));
MiddleApproval.Advisors.Add(new Advisor(user, form, MiddleApproval));
MiddleApproval.Viewers.Add(new Viewer(user, form, MiddleApproval));
MiddleApproval.StageName = "Middle Approval";
ApprovalStage FinalApproval = new ApprovalStage();
FinalApproval.StageOrder = 3;
FinalApproval.Approvers = new List<ReqApprover>();
FinalApproval.Advisors = new List<Advisor>();
FinalApproval.Viewers = new List<Viewer>();
FinalApproval.Form = form;
FinalApproval.ApprovalProcess = process;
FinalApproval.Approvers.Add(new ReqApprover(user, form, FinalApproval));
FinalApproval.Advisors.Add(new Advisor(user, form, FinalApproval));
FinalApproval.Viewers.Add(new Viewer(user, form, FinalApproval));
FinalApproval.StageName = "Final Approval";
process.Stages = new List<ApprovalStage>();
process.Stages.AddRange(new ApprovalStage[] { InitialReview, MiddleApproval, FinalApproval });
//set default values
process.Approved = false;
process.Denied = false;
process.CurrentStage = 1;
process.Stages[0].StartStage();
return process;
}
public void SaveToDb()
{
//make sure we have at least one stage and either a form reference (new form) or form id (old form) before moving forward
if ((Stages != null && Stages.Count > 0) && (Form != null || FormId > 0))
{
using (TechnologyProjectPlanContext db = new TechnologyProjectPlanContext())
{
//first we have to save the process to get an Id
//copy stages out so we can save without the fuss
List<ApprovalStage> stages = this.Stages;
this.Stages = null;
db.ComplexApprovalProcesses.Add(this);
db.SaveChanges();
//'this' now has an Id
//ok let's work it out from the bottom to the top, first separate out approvers from stages and save:
foreach (ApprovalStage stage in stages)
{
ICollection<ReqApprover> approvers = stage.Approvers;
ICollection<Advisor> advisors = stage.Advisors;
ICollection<Viewer> viewers = stage.Viewers;
stage.FormId = stage.Form.Id;
stage.Form = null;
stage.Approvers = null;
stage.Advisors = null;
stage.Viewers = null;
stage.ApprovalProcessId = this.Id;
db.ApprovalStages.Add(stage);
db.SaveChanges();
//stage now has an id;
//iterate through each set of approvers and save
foreach (Approver approver in approvers)
{
approver.FormId = stage.FormId;
approver.UserId = approver.User.Id;
approver.ApprovalStage_Id = stage.Id;
approver.Form = null;
approver.User = null;
approver.Stage = null;
db.Approvers.Add(approver);
db.SaveChanges();
}
foreach (Advisor approver in advisors)
{
approver.FormId = stage.FormId;
approver.UserId = approver.User.Id;
approver.ApprovalStage_Id = stage.Id;
approver.Form = null;
approver.User = null;
approver.Stage = null;
db.Approvers.Add(approver);
}
foreach (Viewer approver in viewers)
{
approver.FormId = stage.FormId;
approver.UserId = approver.User.Id;
approver.ApprovalStage_Id = stage.Id;
approver.Form = null;
approver.User = null;
approver.Stage = null;
db.Approvers.Add(approver);
}
db.SaveChanges();
}
}
}
}
}
public class ApprovalStage
{
//Each stage requires at least one approver
[Key]
public long Id { get; set; }
[ForeignKey("ApprovalProcess")]
public long ApprovalProcessId { get; set; }
[ForeignKey("Form")]
public long FormId { get; set; }
public FormBase Form { get; set; }
public ComplexApprovalProcess ApprovalProcess { get; set; }
public ICollection<ReqApprover> Approvers { get; set; } //These users are required to approve before the form can move to the next stage.
public ICollection<Advisor> Advisors { get; set; } //These users can see the form and approve at this stage, but they are not required.
public ICollection<Viewer> Viewers { get; set; } //These users can see the form, but cannot approve
public string StageName { get; set; } //Name of stage e.g. Review, Final Approval, etc. Gives a custom feel?
public int StageOrder { get; set; }
public bool Completed { get; set; }
public bool Approved { get; set; }
public bool Denied { get; set; }
public bool CanAbstain { get; set; }
public ApprovalStage()
{
this.Approved = false;
this.Denied = false;
this.Completed = false;
}
}
public class Approver
{
[Key]
public long Id { get; set; }
[ForeignKey("User")]
public int UserId { get; set; }
public UsersModel User { get; set; }
[ForeignKey("Form")]
public long FormId { get; set; }
public FormBase Form { get; set; }
[ForeignKey("Stage")]
public long ApprovalStage_Id { get; set; }
public ApprovalStage Stage { get; set; }
public bool Approved { get; set; }
public bool Denied { get; set; }
public bool Abstain { get; set; }
public Approver() { }
public Approver(UsersModel user, FormBase form, ApprovalStage stage)
{
this.Stage = stage;
this.User = user;
this.Approved = false;
this.Denied = false;
this.Abstain = false;
}
}
Ok so I figured out the error I was making. I didn't think about the fact that once placed into the database, the different lists of the same object type would have no knowledge of which list they originated from. That is, an Approver, Advisor, and Viewer would all look the same to the framework after they've been inserted. I kept running into errors with the inheritance of Approvers, so I simply made 3 different classes and tables and copied the design to each of them and it works perfectly. Can't believe I spent so much time on this...

Test data to build tree menu using recursive method?

I can't seem to get my head around this. I need to build some test data to build a tree menu, but I either get a stackverflow error because it just keeps going or I only get the first level of children. Here is the code I currently have:
private MenuItem _menuItem;
private int _start = 1;
private const int Stop = 5;
public void BuildMenu()
{
var numberOfChildren = new Random((int) DateTime.Now.Ticks).Next(3, 40);
AutoMapper.Mapper.CreateMap<MenuItem, MenuItemDto>().ConvertUsing<MenuItemConverter>();
_menuItem = new MenuItem() {Id = Guid.NewGuid(), Name = "Main Menu"};
_menuItem.ChildMenuItems = BuildChildItems(_menuItem, numberOfChildren);
var menuDto = AutoMapper.Mapper.Map<MenuItem, MenuItemDto>(_menuItem);
}
public ICollection<MenuItem> BuildChildItems(MenuItem parentMenuItem, int numberOfChildren)
{
var childItems = new Collection<MenuItem>();
_start += 1;
for (var i = 0; i <= numberOfChildren; i++)
{
var childItem = new MenuItem()
{
Id = Guid.NewGuid(),
ParentItemId = parentMenuItem.Id,
Parentitem = parentMenuItem,
Name = "Child Menu Item " + DateTime.Now
};
if (_start != Stop)
{
childItem.ChildMenuItems = BuildChildItems(childItem, numberOfChildren);
}
childItems.Add(childItem);
}
return childItems;
}
public class MenuItem
{
public Guid Id { get; set; }
public string Name { get; set; }
public Guid? ParentItemId { get; set; }
public MenuItem Parentitem { get; set; }
public ICollection<MenuItem> ChildMenuItems { get; set; }
}
While this works, you will notice the _start and Stop variables. I put those in so I don;t get a stackoverflow, but obviously that is why I only get the 1st level of each with populated children. I figure I would need to track what level I am in, but not sure how to keep track of it. Not sure why I am drawing a blank today....
This gives the idea rather than actually looking at your specific object model! Have an int which represents the number of levels you want to go to. Send this into the method, decrement it on each recurse until it is zero.
public void BuildChildItems(MenuItem parentMenuItem, int numberOfChildren, int level)
{
if(level == 0) return;
var results_for_this_level = create_results_for_this_level();
parentMenuItem.Add(results_for_this_level);
foreach(sibling in results_for_this_level)
{
BuildChildItems(sibling, numberofChildren, level-1) //note the decrement of level here
}
}

Categories