ASP.NET adding data to class in loop - c#

I have this code here:
for (int i = 0; i < reader.FieldCount; i++)
{
RedBlue item = new RedBlue();
if (reader.GetName(i).ToString().Contains("BID"))
{
item.baselinefinish = reader.GetValue(i).ToString();
}
if (reader.GetName(i).ToString().Contains("AID"))
{
item.actualenddate = reader.GetValue(i).ToString();
}
redBlue.Add(item);
}
What I am trying to do loop through data and add it to a class, but my problem is in my class I have two strings and I want to populate each string like this (first string gets the first item in the loop, the second string get the second item in the loop, and keep going like that, so instead of each one in the loop, for every two items in the loop add them to the string and continue on....I really hope this makes sense. Anyone know how I would accomplish this?
Currently what is happening, is it will add one of the strings to the class and then add the second string to a new class.

You can use Automapper and do something like this :
(adapted from what I remember of this framework, the docs here and your example)
// Configure AutoMapper
Mapper.Initialize(cfg =>
cfg.CreateMap<YourReaderClass, RedBlue>()
.ForMember(dest => dest.baselinefinish , opt => opt.MapFrom(src => src.BID))
.ForMember(dest => dest.actualenddate , opt => opt.MapFrom(src => src.AID))
// Perform mapping
RedBlue item = Mapper.Map<YourReaderClass, RedBlue>(reader);
You do the configuration once somewhere and then you can perform as many mapping you want. Of course, you have to manually indicate which field is mapped to which field with as many ForMember as you need.
EDIT
Actually, you could of course still do it without 3rd party, as you were thinking. To solve the specific problem with your method :
Currently what is happening, is it will add one of the strings to the
class and then add the second string to a new class.
(by the way, you mean instance of your class (object), not class )
Of course this happening, because you are creating new objects each time you iterate your loop !
If you do it like this, it should work :
// instantiate your object once, before the loop :
RedBlue item = new RedBlue();
for (int i = 0; i < reader.FieldCount; i++)
{
if (reader.GetName(i).ToString().Contains("BID"))
{
item.baselinefinish = reader.GetValue(i).ToString();
}
if (reader.GetName(i).ToString().Contains("AID"))
{
item.actualenddate = reader.GetValue(i).ToString();
}
}
// now you have one object named 'item' which should be what you want.

Not sure I follow, but right now you are creating a new object at every iteration and therefore each object will have only either string.
If your data is as you say, containing BID every second and AID every second element, as a poor mans solution, you could simply increment the i after adding the first string.
for (int i = 0; i < reader.FieldCount; i++)
{
RedBlue item = new RedBlue();
if (reader.GetName(i).ToString().Contains("BID"))
{
item.baselinefinish = reader.GetValue(i).ToString();
i++;
}
if (reader.GetName(i).ToString().Contains("AID"))
{
item.actualenddate = reader.GetValue(i).ToString();
}
redBlue.Add(item);
}
Or maybe I'm missing something?

Not sure if I follow your idea, but you can use even or odd index number to represent the first and second item on the loop.
Something like that:
for (int i = 0; i < reader.FieldCount; i++)
{
RedBlue item = null;
//if it's even index number
if(i % 2 == 0){
item = new RedBlue();
redBlue.Add(item);
if (reader.GetName(i).ToString().Contains("BID"))
item.baselinefinish = reader.GetValue(i).ToString();
}else{
if (reader.GetName(i).ToString().Contains("AID"))
item.actualenddate = reader.GetValue(i).ToString();
}
}

Related

Does expanding arraylist of objects make a new object?

Assume we have an array list of type Employe , does expanding it's length by 1 make a new object in the list ?
is the code in else statement correct? and is it recommended?
public void ModifierEmp(int c)
{
for(int i = 0; i < Ann.Count; i++)
{
if(Ann[i].Code == c)
{
Ann[i].saisie();
} else
{
i = Ann.Count + 1; //expanding arraylist ann
Ann[i].saisie(); //saisie a method for the user to input Employe infos
}
}
}
https://imgur.com/VfFHDKu "code snippet"
i = Ann.Count + 1;
The code above is not expanding the list: it is only setting your index variable (i) to have a new value.
If you wanted to make the list bigger, you would have to tell it which object to put into that new space you create. For example:
Ann.Add(anotherItem);
Of course, this gives you the ability to decide whether to add an existing item, create a new item (e.g. Ann.Add(new Something() { Code = c })), or even add a null value to the list (which is not usually a good idea).

c# collections and re-numbering not working as expected

Hi i'm trying to setup simple test data.
I simply want to take a collection which is smallish and make it bigger by add itself multiple times.
After I;ve added them together i want to re-number the property LineNumber
so that there are no duplicates and that it goes in order. 1,2,3,4....
no matter what i try it doesn't seem to work and i cant see the mistake.
var sampleTemplateLine = dataContext.TemplateFileLines.ToList();
*//tired this doesnt work either*
//List<TemplateFileLine> lineRange = new List<TemplateFileLine>();
//lineRange.AddRange(sampleTemplateLine);
//lineRange.AddRange(sampleTemplateLine);
//lineRange.AddRange(sampleTemplateLine);
//lineRange.AddRange(sampleTemplateLine);
var allProducts = sampleTemplateLine
.Concat(sampleTemplateLine)
.Concat(sampleTemplateLine)
.Concat(sampleTemplateLine)
.ToList();
int i = 1;
foreach (var item in allProducts)
{
item.LineNumber = i;
i++;
}
this doesnt seem to work either
//re-number the line number
var total = allProducts.Count();
for (int i =0; i < total; i++)
{
allProducts[i].LineNumber = i+1;
}
PROBLEM: below RETURN 4 when i'm expecting 1
var itemthing = allProducts.Where(x => x.LineNumber == 17312).ToList();
You are adding the same objects multiple times. You wold have to add new objects or clone the ones you have.
The problem is they are pointing the same object. So if you change a property it changes all the pointed objects at the same
You can use Clone method if it exist, if not you can create your own Clone method like in this question.

Getting a string to be a variable name

I found this question but it's being used with an XML file so I don't really understand what is going on.
What I want to do is get my list of objects to get populated in my for loop. Right now I have this:
for (int i = 0; i < dogs.Length; i++)
{
dogs[i] = new Dog();
}
dogs[0].PictureBox = picDog0;
dogs[1].PictureBox = picDog1;
dogs[2].PictureBox = picDog2;
dogs[3].PictureBox = picDog3;
I want to do something like this:
for (int i = 0; i < dogs.Length; i++)
{
dogs[i] = new Dog();
dogs[i].PictureBox = StringToVariable("picDog" + i);
}
PictureBox is a property field in case that makes a difference.
StringToVariable() is the thing I don't know about. I don't even know what it would be called to search for it.
It's impossible to say for sure without a good, minimal, complete code example. But I would expect that the following statement should work in your scenario:
dogs[i].PictureBox = (PictureBox)Controls.Find("picDog" + i, true)[0];
That will search the children of the current control (which I assume in this case is your Form subclass) for each control in turn. This is somewhat inefficient, as it has to search the controls collection for each item, but as long as you have a relatively small number of items, this is likely not a problem.
Depending on how your Form is set up, the following might also work:
string prefix = "picDog";
foreach (PictureBox pictureBox in Controls.OfType<PictureBox>())
{
if (pictureBox.Name.StartsWith(prefix))
{
int index;
if (int.TryParse(pictureBox.Name.Substring(prefix.Length), out index))
{
dogs[index] = pictureBox;
}
}
}
That version inspects each child control just once, attempting to parse an index appended to the initial text of "picDog", and if it's successful, using that index to assign to your array directly. This has the advantage of scaling well to larger lists of controls, but may be overkill in your case.
Note that in both of the above examples I've left out any error checking. In either example, you would probably want to add some kind of handling in case (for the first example) the desired control couldn't be found, or (for the second example) if you find a control for which you can't parse the index, or fail to fill in one of the elements of the dogs array.
If for some reason neither of the above examples seem to work for you, please edit your post so that it includes a better code example.
Sometimes a simple solution can work well. How about this?
var picDogs = new [] { picDog0, picDog1, picDog2, picDog3 };
for (int i = 0; i < dogs.Length; i++)
{
dogs[i] = new Dog();
dogs[i].PictureBox = picDogs[i];
}
You could even do this:
var dogs = new [] { picDog0, picDog1, picDog2, picDog3 }
.Select(picDog => new Dog() { PictureBox = picDog })
.ToArray();

Loop through ICollection and set to null

I need to remove the data from an ICollection if the ID of the collection is in a List of ID's.
What I have so far:
foreach (var notSelectedToolId in notSelectedToolIds)
{
for (int i = 0; i < matchingHoleInfoVm.ToolHeader.Count; i++)
{
if (matchingHoleInfoVm.ToolHeader.ElementAt(i).ToolID == notSelectedToolId)
{
matchingHoleInfoVm.ToolHeader.ElementAt(i) = new ToolHeaderViewModel();
}
}
}
The error I get: "This expression cannot be used as an assignment target".
How can I make this work?
You can't, basically - not with just ICollection (or even ICollection<T>). Neither of them allow you to replace an existing element with a new one.
With IList<T>, it's pretty easy:
var list = matchingHoleInfoVm.ToolHeader;
for (int i = 0; i < list.Count; i++)
{
if (list[i].ToolID == notSelectedToolId)
{
list[i] = new ToolHeaderViewModel();
}
}
In most cases where you've already got an ICollection<T>, you'll find it already implements IList<T>. If it doesn't, you need to look carefully at what the collection actually is, and consider whether "replace at the same index" even makes sense. (If it's a HashSet<,>, for example, you can just remove the existing item and add a new one...)
EDIT: If you only need to remove the items, you can just use the Remove method:
var itemsToRemove = collection.Where(c => c.ToolID == notSelectedToolId).ToList();
.ToList();
foreach (var item in itemsToRemove)
{
collection.Remove(item);
}
Additionally, you don't need nested loops - you can use something like:
var itemsToRemove = collection.Where(c => notSelectedToolIds.Contains(c.ToolID))
to find all of the ones to remove in a single pass (then remove them as above).
You could apply a filter to the matchingHoleInfoVm.ToolHeader using LINQ to return a new list. Something like
var toolsExlcuded = matchingHoleInfoVm.ToolHeader.Where(x => !notSelectedToolIds.Contains(x.ToolId)).ToList();

How do I create a Dictionary<int, EntityState>, and add values inside a for loop?

So, I hope this is simple. I'm coming up with a way to store disconnected entities (due to my case being quite peculiar), and for it to work, I'd like to create a Dictionary with those values inside a for loop.
But I'm getting "An item with the same key" has been added problem, which I do not know why.
I've tried the following:
Dictionary<int, EntityState> StateProduct = new Dictionary<int, EntityState>();
for (int s = 0; s < userProducts.Count; s++ ) //userProducts.Count had value of 3
{
StateProduct.Add(s, EntityState.Modified);
}
But I get the error:
In which:
I really really do not know what's going on..
Edit: Here is the complete code
var dbIboID = dbs.OrderDB.Where(x => x.OrderID == Order[0].OrderID).FirstOrDefault();
if(dbIboID.IboID != uid)
{
return false;
}
//2nd Step:
//2.0 Attach it. Yes I know it sets it as unchanged. But let me do the magic trick!!!
dbIboID.OrderProcess = Order.ToList(); //CHANGED
dbs.OrderDB.Attach(dbIboID);
//2.1 Extract original values from the database.
var originalProducts = dbs.OrderProcessDB.Where(x => x.OrderProcessID == Order[0].OrderProcessID).ToList();
var userProducts = Order.ToList();
//This is a dictionary which will be used to set all other entities with their correct states!
Dictionary<int, System.Data.Entity.EntityState> StateProduct = new Dictionary<int, System.Data.Entity.EntityState>();
//2.3 Find new added products. addedProducts = userProducts[key] - originalProducts[key]
if(userProducts.Count > originalProducts.Count)
{
for (int i = originalProducts.Count - 1; i < userProducts.Count; i++ )
{
StateProduct.Add(i, System.Data.Entity.EntityState.Added);
}
}
//2.3 Find Deleted products = originalProducts - userProducts. Do reverse of the addedProducts
else
{
for (int i = userProducts.Count - 1; i < originalProducts.Count; i++)
{
StateProduct.Add(i, System.Data.Entity.EntityState.Deleted);
}
}
//2.4 Find modified products modifiedProducts = [userProducts - addedProducts] different originalProducts
//This is not 100% fool proof. Because there will be times that I will always have a modification,
// when objects remained unchanged.
for (int s = 0; s < userProducts.Count; s++ )
{
StateProduct.Add(s, System.Data.Entity.EntityState.Modified);
}
//2.5 Painting Process:
for (int i = 0; i < dbIboID.OrderProcess.Count(); i++ )
{
dbs.DB.Entry(dbIboID.OrderProcess[i]).State = StateProduct[i];
}
The code as you have shown it should not produce that exception, because the dictionary was allocated immediately prior to the loop, and thus should be empty, and the items being added all are unique integers.
My guess is that the dictionary already had some values in it. If so, then using Add to set a value will throw an ArgumentException, since the value corresponding to that key can only be replaced, not added, for the Dictionary class only allows one value per key.
So, if you expect the dictionary not to already have a value for a key, and want an error exception to be thrown if it does, do:
StateProduct.Add(s, EntityState.Modified)
If you want to add or replace a value, do:
StateProduct[s] = EntityState.Modified;

Categories