Loop and update object value in a collection using LINQ - c#

I want to iterate through each object in a collection and then update a property on each object with another array collection
My use case is I have some entities which I initially read from my collection into an array, and perform some complex calculation and then update back my original collection.
public void WhatIfCalculation(string Product, string SiteID, System.Linq.IQueryable<DAL.OMS_StockStatus> prodStatus, ref System.Linq.IQueryable<PivotViewModel> activityInfo)
{
var sff = activityInfo.Where(a => a.Activity == "System Forecast" && a.SiteID == SiteID).ToList();
aSFF = new double?[sff.Count()];
for (int i = 0; i < sff.Count(); i++)
{
aSFF[i] = sff.ElementAt(i).Value + 1;
}
var prf = activityInfo.Where(a => a.Activity == "Planned Receipts" && a.SiteID == SiteID).ToList();
aPRF = new double?[prf.Count()];
for (int i = 0; i < prf.Count(); i++)
{
aPRF[i] = prf.ElementAt(i).Value + 2;
}
// Will perform some calculation here. And then update back my collection.
for (int i = 0; i < aSFF.Length; i++)
{
activityInfo.Where(a => a.Activity == "System Forecast" && a.SiteID == SiteID).ToList().ElementAt(i).Value = aSFF[i];
}
for (int i = 0; i < aPRF.Length; i++)
{
activityInfo.Where(a => a.Activity == "Planned Receipts" && a.SiteID == SiteID).ToList().ElementAt(i).Value = aPRF[i];
}
}
But above update is not updating my collection. When I browse back through my activityInfo - its still showing original value.

Try the following:
public void WhatIfCalculation(string Product, string SiteID, List<DAL.OMS_StockStatus> prodStatus, List<PivotViewModel> activityInfo)
{
var sff = activityInfo.Where(a => a.Activity == "System Forecast"); // Do this in the calling function >> .Where(a => a.SiteID == SiteID).ToList();
aSFF = new double?[sff.Count()];
for (var i = 0; i < sff.Count(); i++)
{
aSFF[i] = sff.ElementAt(i).Value + 1;
}
var prf = activityInfo.Where(a => a.Activity == "Planned Receipts");
aPRF = new double?[prf.Count()];
for (var i = 0; i < prf.Count(); i++)
{
aPRF[i] = prf.ElementAt(i).Value + 2;
}
// Will perform some calculation here. And then update back my collection.
for (var i = 0; i < aSFF.Length; i++)
{
sff.ElementAt(i).Value = aSFF[i];
}
for (var i = 0; i < aPRF.Length; i++)
{
prf.ElementAt(i).Value = aPRF[i];
}
}
As you can see I am sending a list instead of an IQueryable to the method. Reason is that the IQueryable is in fact an query statement and not the record itself.
Basically what you are doing is sending a query to the method which you than use to select the items and change them. The actual items are not changed.
Using the below example you are sending a list of the actual items. The items can than be changed. I also removed some double select statements from your method to enhance the speed.
this should also be useful: Differences between IQueryable, List, IEnumerator?

Related

Trying to change an element in a Collection

I'm trying to modify this code. I need to check for a value in a specific element of FilteredCheckObservable and if true, change the value of another part of that element.
Basically something like
if (FilteredCheckObservable items.Lang = 'ENG')
{items.check = newcheckname;}
Then this will update the sourceGroups Collection.
if (string.IsNullOrEmpty(departmentLine.LineID) || string.IsNullOrEmpty(departmentLine.LineName))
continue;
bool discovered = false;
foreach (var group in sourceGroups)
{
if (!group.Key.Line.IsEqual(departmentLine))
continue;
group.Key.IsDiscovered = true;
discovered = true;
group.Key.ScheduleStatusCount = group.CountGroupItem;
break;
}
if (discovered == false)
{
var _ScheduleItemObservable = new ScheduleItemObservable(departmentLine, MainViewViewModel, Shift.ToString());
var item = new Grouping<ScheduleItemObservable, FilteredCheckObservable>(_ScheduleItemObservable);
if (IsShiftValid)
{
item.Key.Shift = Shift.ToString();
item.Key.IsHistoryEnabled = true;
}
sourceGroups.Add(item);
}
for (int index = 0; index < sourceGroups.Count; index++)
{
if (sourceGroups[index].Key.IsDiscovered == true)
{
foreach (var group in sourceGroups)
{
foreach (FilteredCheckObservable items in group)
{
if (items.Lang_ID == LanguageService.Instance.LanguageType.ToString())
{
sourceGroups.Clear();
sourceGroups.Add(item);
}
}
}
}
}
Welcome Travis,
I would wager the guilty culprit is your foreach loop.
https://stackoverflow.com/a/759985/3403999
You aren't allowed to modify a collection inside of a foreach loop.
I don't know if your collection has an indexer, but if it does, you can convert to a for loop:
for (int i = 0; i < sourceGroups.Count; i++)
{
var group = sourceGroups[i];
// The rest of your code.
I could be wrong. You do say you are trying to modify some existing code. Is it some code that is online? Maybe you could link to it to provide a full context.
Based on your new snippet, you need two for loops:
for (int index = 0; index < sourceGroups.Count; index++)
{
if (sourceGroups[index].Key.IsDiscovered == true)
{
//foreach (var group in sourceGroups)
for (int j = 0; j < sourceGroups.Count; j++)
{
var group = sourceGroups[j];
foreach (FilteredCheckObservable items in group)
{
if (items.Lang_ID == LanguageService.Instance.LanguageType.ToString())
{
sourceGroups.Clear();
sourceGroups.Add(item);
}
}
}
}
}
^ Although that might still be a bad loop. Primarily because you have sourceGroups.Clear();.
What you might be better off doing is creating an internal collection called say 'results'. Do your loop looking for your conditions, and if they meet, add that item to the results collection.
Once your loops terminate, then call sourceGroups.Clear(), and then sourceGroups.AddRange(results). If sourceGroups doesn't have an AddRange, then one final loop of:
foreach (var group in results) { sourceGroups.Add(group); }

I have SQLite db with 3 rows, when i delete data from row, data will lost but row will still, how can i delete that blank row?

I have xamarin app and I am using SQLite for saving data, if I have 3 rows and delete second row, then data will delete but row will be blank and its still here and problem is, that I need to load one column from every row. I am using for cycle and count to set maximum for it. But count says I have two rows so for cycle load just first and not second because second is on third line and second is blank.
I need to delete blank rows or to discover another solution how to load it. How can i delete blank DB?
Counting algorythm:
public int GetNumberPhotos()
{
var db = new SQLiteConnection(_dbPath);
db.CreateTable<Airplane>();
int count = 0;
if (db.Table<Airplane>().FirstOrDefault(l => l.Id == 1) != null)
count = db.Table<Airplane>().Count();
return count;
}
loading:
public int BetterUniReg()
{
int numberPhotos = GetNumberPhotos();
string[] allReg = new string[numberPhotos];
string[] uniReg = new string[numberPhotos];
int uniRegCnt = 0;
var db = new SQLiteConnection(_dbPath);
//db fill
for (int i = 0; i <= numberPhotos; i++)
{
if (db.Table<Airplane>().FirstOrDefault(b => b.Id == i) != null)
{
var rowData = db.Table<Airplane>().FirstOrDefault(c => c.Id == i);
i--;
allReg[i] = rowData.Registration;
i++;
}
}
Here is delete code:
private async void deleteButton_Clicked(object sender, EventArgs e)
{
var action = await DisplayAlert("Delete", "Do you want delete picture?", "Cancel", "Delete");
if (action)
{
}
else
{
var butto = sender as Button;
var frame = butto.Parent.Parent.Parent.Parent as Frame;
await frame.FadeTo(0, 600);
var button = (Button)sender;
var plane = (Airplane)button.BindingContext;
var db = new SQLiteConnection(_dbPath);
db.Delete<Airplane>(plane.Id);
Refresh();
}
}
I have done walkaround by adding if its last row and its null then do one more cycle.
Here is code:
for (int i = 1; i <= numberPhotos; i++)
{
if (db.Table<Airplane>().FirstOrDefault(c => c.Id == i) != null)
{
var rowData = db.Table<Airplane>().FirstOrDefault(c => c.Id == i);
allReg[regnumber] = rowData.Registration;
regnumber++;
}
if (db.Table<Airplane>().FirstOrDefault(c => c.Id == i) == null && i == numberPhotos)
{
numberPhotos = numberPhotos + 1;
}
}

Telerik Radlistview dynamically grouping items

using winform I am trying to display from database the fooditems that are grouped under categories into a radlistview using that below code; but the Problem that it is showing the main Groups but not showing the items under it.
ZalaqEntities1 zlq=new ZalaqEntities1();
List<cat> cats = zlq.cats.ToList();
radListView1.Items.Clear();
radListView1.Groups.Clear();
radListView1.EnableGrouping = true;
radListView1.ShowGroups = true;
for (int i = 0; i < cats.Count(); i++)
{
radListView1.Groups.Add(new ListViewDataItemGroup());
radListView1.Groups[i].Value = cats[i].catname;
radListView1.Groups[i].Key = cats[i].catid;
}
List<fooditem> fooditems = zlq.fooditems1.ToList();
for (int j = 0; j < fooditems.Count(); j++)
{
ListViewDataItem myitem = new ListViewDataItem();
myitem.Value = fooditems[j].itemname;
myitem.Key = fooditems[j].itemid;
// myitem.Group = radListView1.Groups[1];
radListView1.Items.Add(myitem);
myitem.Group = radListView1.Groups.Where(i => i.Key == fooditems[j].catid).FirstOrDefault();
//radListView1.Items[j].Group = radListView1.Groups[1];
}
radListView1.Refresh();
I am trying to add the Item under its category using the where condition to find the correct group by its Key.
If I do this outside for Loop it was working for adding several Items.but from database inside the for loop non.
The Problem was just by casting the i.Key.ToString() inside the Where Clause ..
the Final Code :
ZalaqEntities1 zlq=new ZalaqEntities1();
List<cat> cats = zlq.cats.ToList();
radListView1.Items.Clear();
radListView1.Groups.Clear();
radListView1.EnableGrouping = true;
radListView1.ShowGroups = true;
for (int i = 0; i < cats.Count(); i++)
{
ListViewDataItemGroup grp = new ListViewDataItemGroup();
grp.Value = cats[i].catname;
grp.Key = cats[i].catid.ToString();
radListView1.Groups.Add(grp);
radListView1.Groups[i].Key = cats[i].catid;
}
radListView1.Refresh();
List<fooditem> mfooditems = zlq.fooditems1.ToList();
for (int j = 0; j < mfooditems.Count(); j++)
{
ListViewDataItem myitem = new ListViewDataItem();
myitem.Value = mfooditems[j].itemname;
myitem.Key = mfooditems[j].itemid;
radListView1.Items.Add(myitem);
radListView1.Refresh();
radListView1.Items[j].Group = radListView1.Groups.Where(i => i.Key.ToString() == mfooditems[j].catid.ToString()).FirstOrDefault();
}
radListView1.Refresh();

C# and excel cubefield item list

I'm trying to automate testing of excel add-in that allows you to create some analysis entities based on pivot table definition.
I'm able to create random pivot table using cubefield objects(I'm adding random fields to rows,columns, and measures) but I need also to add some filtering and here I'm stuck.
Is there any way to get cubefield item list ? For example when I have date field in filter
list of all days and then I want to select some random days for filtering.
This is my code maybe it's not elegant but it works for my purpose.
I'm basically grabbing cubefields check if it's measure or dimension and then I'm setting
it's orientation.
public void PivotTableFieldList()
{
_currentPivotTable = (Excel.PivotTable) _worksheet.PivotTables("PivotTable1");
_currentPivotTable.ManualUpdate = true;
List<Excel.CubeField> measureList = new List<Excel.CubeField>();
List<Excel.CubeField> dimensionList = new List<Excel.CubeField>();
foreach (Excel.CubeField field in _currentPivotTable.CubeFields)
{
if (field.CubeFieldType == Excel.XlCubeFieldType.xlMeasure && field.ShowInFieldList)
{
measureList.Add(field);
}
}
foreach (Excel.CubeField field in _currentPivotTable.CubeFields)
{
if (field.CubeFieldType != Excel.XlCubeFieldType.xlMeasure && field.ShowInFieldList)
{
dimensionList.Add(field);
}
}
Random dimRan=new Random();
dimRan.Next(0, dimensionList.Count);
Random mesRan = new Random();
mesRan.Next(0, measureList.Count);
dimensionList.ToArray();
measureList.ToArray();
Excel.CubeField[] measureRandomList= new Excel.CubeField[3];
Excel.CubeField[] dimensionRandomList = new Excel.CubeField[6];
for (int i = 0; i < 3; i++)
{
measureRandomList[i] = measureList[mesRan.Next(1, measureList.Count)];
}
for (int i = 0; i < 6; i++)
{
dimensionRandomList[i] = dimensionList[dimRan.Next(i, dimensionList.Count)];
}
for (int i = 0; i < 3; i++)
{
var field = measureRandomList[i];
var name = measureRandomList[i].Name;
field.Orientation= Excel.XlPivotFieldOrientation.xlDataField;
}
dimensionRandomList[0].Orientation= Excel.XlPivotFieldOrientation.xlRowField;
dimensionRandomList[1].Orientation = Excel.XlPivotFieldOrientation.xlColumnField;
dimensionRandomList[2].Orientation = Excel.XlPivotFieldOrientation.xlPageField;
dimensionRandomList[2].EnableMultiplePageItems=true;
//How can I get cubefield items list ?
}
You can filter your fields like this:
yourPivotField.CurrentPageName = string.Format("[{0}].[{1}].&[{2}]", SheetName, FieldName, FieldValue);
This sets the filter of your pivot table
Not sure if it it this you were searching for.

Separating Records into indvidual months for mvc

I have a collection of records. Which have two boxers, match date, location etc...
I want to separate them by months and group them together. Currently I have what is below. And it works to a degree. That looks for matchdates in the future. that is this year and steps through each month (1-12) and finds any matches in that date range.
Placing it into a nice dictionary of int, enumerable where int is the month and enumberable is the collection of matches in that month
//Build the matches list by Months!!!
var summarysDic = new Dictionary<int, IEnumerable<MatchSummary>>();
for (int i = 1; i <= 12; i++)
{
var MatchesOfMonth = matches.Where(x => x.MatchDate.Value.Year == DateTime.Now.Year &&
x.MatchDate.Value.Month == i &&
!x.HasResult() &&
x.MatchDate.Value > DateTime.Now);
if (MatchesOfMonth.Count() > 0)
{
summarysDic.Add(i, MatchesOfMonth.OrderBy(x => x.MatchDate).Select(x=> new MatchSummary(x)).ToArray());
}
}
Problem is this currently only deals with this year. I would like to instead make it so it works for "the next 6 months" but this would of course have to work over the new year as well!
Whats the best/cleanest way to go about doing this?
thanks in advance!
P.S on a side note i have yet to find how to simply do DateTime.Now.Month.add(1) for example (as i will always be going from current date forwards!)
-----COMPLETED CODE!-----
//Build the matches list by Months!!!
var summarysDic = new Dictionary<string, IEnumerable<MatchSummary>>();
for (int i = 1; i <= 12; i++)
{
var checkDate = DateTime.Now.AddMonths(i);
var MatchesOfMonth = matches.Where(x => x.MatchDate.Value.Month == checkDate.Month &&
x.MatchDate.Value.Year == checkDate.Year &&
!x.HasResult() &&
x.MatchDate.Value > DateTime.Now);
if (MatchesOfMonth.Count() > 0)
{
var firstMatchDate = MatchesOfMonth.First().MatchDate.Value;
if (firstMatchDate.Year != DateTime.Now.Year)
{
summarysDic.Add(firstMatchDate.ToString("MMMM yyyy"), MatchesOfMonth.OrderBy(x => x.MatchDate).Select(x => new MatchSummary(x)).ToArray());
}
else
{
summarysDic.Add(firstMatchDate.ToString("MMMM"), MatchesOfMonth.OrderBy(x => x.MatchDate).Select(x => new MatchSummary(x)).ToArray());
}
}
}
I believe you can get what you want without modifying your algorithm significantly:
//Build the matches list by Months!!!
var summarysDic = new Dictionary<int, IEnumerable<MatchSummary>>();
for (int i = 0; i <= 6; i++)
{
var checkDate = DateTime.Now.AddMonths(i);
var MatchesOfMonth = matches.Where(x => x.MatchDate.Value.Year == checkDate.Year &&
x.MatchDate.Value.Month == checkDate.Month &&
!x.HasResult() &&
x.MatchDate.Value > DateTime.Now);
if (MatchesOfMonth.Count() > 0)
{
summarysDic.Add(i, MatchesOfMonth.OrderBy(x => x.MatchDate).Select(x=> new MatchSummary(x)).ToArray());
}
}
What's wrong with DateTime.Now.AddMonth(1)?
var MatchesOfMonth = matches.Where(x => x.MatchDate.Value <= DateTime.Now.AddMonth(i)
&& !x.HasResult()
&& x.MatchDate.Value > DateTime.Now);
I haven't compiled that, but it should run with only fairly minor tweeking...

Categories