VS2010 foreach doesn't appear to be working - visual-studio-2010

This one is strange. Basically, I have a foreach loop: foreach (ApSupplier apSupplierImport in apSuppliers). apSuppliers is a list of ApSupplier objects and ALWAYS contains x number of objects of the ApSupplier class.
I was able to view each apSupplierImport as I stepped through the loop until around noon yesterday. I made a change to the code within the loop (but not to the foreach).
Now, when I hover over the apSupplierImport variable, it shows as null. It appears that it isn't being loaded during the foreach. I believe that there is something in there because the code doesn't error out in the subsequent if I run the original code (though it does when I run the new stuff, which is why I want to see the variable; to figure out what's missing). It's playing hell with debugging, though I'm unsure as to why because I can't see if there is actually something in the variable.
Image showing there are apSuppliers in the list...
Image showing that apSupplierImport variable (of ApSupplier object) is null after iterating...
Any idea what's going on? Is there some setting I'm missing or that may have changed that's causing variables to NOT display? I haven't been able to get it to work after restarting VS2010, rebuilding or a complete reboot. Any suggestions are greatly appreciated.
Here is the complete foreach loop:
foreach (ApSupplier apSupplierImport in apSuppliers)
{
ApSupplier apSupplier = apProperty.ApSuppliers.Where(s => s.Key == apSupplierImport.Key && s.Property.Id == property.Id).FirstOrDefault();
if (apSupplier == null)
{ /*Add new*/
apSupplierImport.ApProperty = apProperty;
apSupplierImport.Property = property;
workspace.Add(apSupplierImport);
}
else /*Update*/
{
apSupplier.Name = apSupplierImport.Name;
apSupplier.Address = apSupplierImport.Address;
apSupplier.Address2 = apSupplierImport.Address2;
apSupplier.City = apSupplierImport.City;
apSupplier.State = apSupplierImport.State;
apSupplier.Zip = apSupplierImport.Zip;
apSupplier.PhoneNumber = apSupplierImport.PhoneNumber;
apSupplier.Property = property;
workspace.Update(apSupplier);
}
}

Related

Setting visiblilty of control using LINQ

I'm working on refactoring some code to practice LINQ. For some reason I can't get this code to cooperate.
//ActionControls is a ControlCollection
var actionControls = flowLayoutPanel1.FilterControls(c => c is Button);
//TODO: Optimize
foreach(var control in actionControls)
{
control.Visible = workingItemDataTable.AsEnumerable().Any(row => "btn" + row.Field<string>("Name") == control.Name);
}
What I am trying to do now.
flowLayoutPanel1.FilterControls(c => c is Button && c.Name == "btnTaskInfo"//btnTaskInfo is always visible
|| workingItemDataTable.AsEnumerable().Any(row => "btn" + row.Field<string>("Name") == c.Name)).Cast<Button>()
But after casting this as a button, I can not figure out how to set visible = false. Any Advice?
You'd still need to iterate the controls, but you can probably do this, assuming FilterControls isn't much more than an alias for Where:
var actionControls = flowLayoutPanel1.OfType<Button>();
There are some "tricks" and shortcuts for iterating and doing sets within a lambda expression, but it makes the code just look messy and they are mostly just hacks. You can create your own extension ForEach (if there isn't one available to you if you really want to do it anyway).
flowLayoutPanel1.OfType<Button>().ForEach(btn=>{btn.Visible= ... });

group.all() call required for data to populate correctly

So I've encountered a weird issue when dealing with making Groups based on a variable when the crossfilter is using an array, instead of a literal number.
I currently have an output array of a date, then 4 values, that I then map into a composite graph. The problem is that the 4 values can fluctuate depending on the input given to the page. What I mean is that based on what it receives, I can have 3 values, or 10, and there's no way to know in advance. They're placed into an array which is then given to a crossfilter. When in testing, I was accessing using
dimension.group.reduceSum(function(d) { return d[0]; });
Where 0 was changed to whatever I needed. But I've finished testing, for the most part, and began to adapt it into a dynamic system where it can change, but there's always at least the first two. To do this I created an integer that keeps track of what index I'm at, and then increases it after the group has been created. The following code is being used:
var range = crossfilter(results);
var dLen = 0;
var curIndex = 0;
var dateDimension = range.dimension(function(d) { dLen = d.length; return d[curIndex]; });
curIndex++;
var aGroup = dateDimension.group().reduceSum(function(d) { return d[curIndex]; });
curIndex++;
var bGroup = dateDimension.group().reduceSum(function(d) { return d[curIndex]; });
curIndex++;
var otherGroups = [];
for(var h = 0; h < dLen-3; h++) {
otherGroups[h] = dateDimension.group().reduceSum(function(d) { return d[curIndex]; });
curIndex++;
}
var charts = [];
for(var x = 0; x < dLen - 3; x++) {
charts[x] = dc.barChart(dataGraph)
.group(otherGroups[x], "Extra Group " + (x+1))
.hidableStacks(true)
}
charts[charts.length] = dc.lineChart(dataGraph)
.group(aGroup, "Group A")
.hidableStacks(true)
charts[charts.length] = dc.lineChart(dataGraph)
.group(aGroup, "Group B")
.hidableStacks(true)
The issue is this:
The graph gets built empty. I checked the curIndex variable multiple times and it was always correct. I finally decided to instead check the actual group's resulting data using the .all() method.
The weird thing is that AFTER I used .all(), now the data works. Without a .all() call, the graph cannot determine the data and outputs absolutely nothing, however if I call .all() immediately after the group has been created, it populates correctly.
Each Group needs to call .all(), or only the ones that do will work. For example, when I first was debugging, I used .all() only on aGroup, and only aGroup populated into the graph. When I added it to bGroup, then both aGroup and bGroup populated. So in the current build, every group has .all() called directly after it is created.
Technically there's no issue, but I'm really confused on why this is required. I have absolutely no idea what the cause of this is, and I was wondering if there was any insight into it. When I was using literals, there was no issue, it only happens when I'm using a variable to create the groups. I tried to get output later, and when I do I received NaN for all the values. I'm not really sure why .all() is changing values into what they should be especially when it only occurs if I do it immediately after the group has been created.
Below is a screenshot of the graph. The top is when everything has a .all() call after being created, while the bottom is when the Extra Groups (the ones defined in the for loop) do not have the .all() call anymore. The data is just not there at all, I'm not really sure why. Any thoughts would be great.
http://i.stack.imgur.com/0j1ey.jpg
It looks like you may have run into the classic "generating lambdas from loops" JavaScript problem.
You are creating a whole bunch of functions that reference curIndex but unless you call those functions immediately, they will refer to the same instance of curIndex in the global environment. So if you call them after initialization, they will probably all try to use a value which is past the end.
Instead, you might create a function which generates your lambdas, like so:
function accessor(curIndex) {
return function(d) { return d[curIndex]; };
}
And then each time call .reduceSum(accessor(curIndex))
This will cause the value of curIndex to get copied each time you call the accessor function (or you can think of each generated function as having its own environment with its own curIndex).

Return value of IEnumerable<T>.Contains changes if called multiple times

I'm having trouble understanding why multiple calls of Contains return different values for the same parameter on the same enumerable.
While I understand that the collection can be modified, thus changing the result in a subsequent call, this can be ruled out here.
Consider the following (stripped-down) code in an MVC view.
The purpose of this will be to display a list of checkboxes (as there's no HTML-helper for that), and determining through the model's properties which ones should be checked when opening the view.
#foreach (var d in Model.AllDomains) {
bool isChecked = Model.Project.Domains.Contains(d.ID);
<input #(isChecked ? "checked=\"checked\" " : "")type="checkbox" value="#d.ID" />
// more stuff here
}
Changing this to use an actual List makes the whole thing work as expected:
var tmp = Model.Project.Domains.ToList();
#foreach (var d in Model.AllDomains) {
bool isChecked = tmp.Contains(d.ID);
<input #(isChecked ? "checked=\"checked\" " : "")type="checkbox" value="#d.ID" />
// more stuff here
}
The following is the model that is bound to my view (again simplified to make it more readable):
public ProjectVM GetByID(int id) {
return new ProjectVM {
Project = new Project {
... // Other properties here
Domains = from d in MyObjectModel.Projects[id].Domains
select d.ID
},
AllDomains = from d in MyObjectModel.Domains
orderby d.Name
select new {
ID = d.ID,
Name = d.Name
}
};
}
Now, while from debugging I know that Model.Project.Domains will contain the correct number of entries, as well as the correct values, calling .Contains() on the method returns an arbitrary result - either true or false.
In fact, if I put the line with the Contains() call into the debugger's "Watch" tab multiple times, even with an hard coded argument (e.g. 4) the result will alternate from true to false with every call.
What is happening here, what am I overlooking?
Because of the way that Model.Project.Domains is instantiated, its actual type is a WhereSelectEnumerableIterator<T>, but this implements IEnumerable<T> so that shouldn't be an issue...
It seems that the root cause of the problem was a sloppy/unusual implementation of the Enumerator in the foundation classes of our object model which made GetEnumerator() return an iterator which was already used in the previous call
Since Contains() stops iterating over the collection after the first match is found, it would return false on such an Enumerator if the seeked value was in the part which had already been searched in the previous iteration.
A negative result of Contains() caused the enumerator to reset internally, which explained the "toggling" result described in my original post.

linq 'range variable' problem

I have a strange problem when deleteting records using linq, my suspicion is that it has something to do with the range variable (named source). After deleting a record all targets for a customer are retrieved using the following statement:
var q = from source in unitOfWork.GetRepository<db_Target>().Find()
where source.db_TargetBase.db_Person.fk_Customer == customerID
select source.FromLinq();
where FromLinq is in extention method on db_target:
public static Target FromLinq(this db_Target source)
{
return new Target
{
id = source.id,
LastModified = source.db_TargetBase.LastModified,
...
}
}
When a record is deleted both db_Target and db_TargetBase are deleted. When, for example, two users are deleting records, linq tries to retrieve a record for user2 which is deleted by user1, causing a crash on the LastModified = source.db_TargetBase.LastModified line because db_TargetBase is null.
When using the following code the problem does not occure and only the non-deleted records are retrieved:
var q = from source in unitOfWork.GetRepository<db_Target>().Find()
where source.db_TargetBase.db_Person.fk_Customer == customerID
select new Target
{
id = source.id,
LastModified = source.db_TargetBase.LastModified,
...
};
This spawns two questions:
What is happening here? Am I making a copy of the range variable source because I'm using it in a extention method?
How can I "wrap" the return new Target code? I am using this in multiple places and do not want to copy it every time. Making my code harder to maintain.
TIA,
JJ
In the first set of code - since the initializer lives an a non-translatable method (extension or otherwise), it cannot be translated - so it is run locally.
In the second set of code - the initializer is represented by an elementinit expression, which is translated (examine/compare the select clause of the generated sql for proof).
if you want to wrap this, you need to have an Expression<Func<db_Target, Target>> that anyone can grab and use in thier query. Fortunately, that's easy to do:
public Expression<Func<db_Target, Target>> GetFromLinqExpressionForTarget()
{
return
source => new Target
{
id = source.id,
LastModified = source.db_TargetBase.LastModified,
...
}
}
Which may be used like so:
var FromLinq = GetFromLinqExpressionForTarget();
var q =
(
from source in ...
...
...
select source
).Select(FromLinq);
Now ... I'm really running on a guess here and am only about 60% confident that my answer is correct. So if someone wants to confirm this, that'll make my day. :)

LINQ to SQL bug (or very strange feature) when using IQueryable, foreach, and multiple Where

I ran into a scenario where LINQ to SQL acts very strangely. I would like to know if I'm doing something wrong. But I think there is a real possibility that it's a bug.
The code pasted below isn't my real code. It is a simplified version I created for this post, using the Northwind database.
A little background: I have a method that takes an IQueryable of Product and a "filter object" (which I will describe in a minute). It should run some "Where" extension methods on the IQueryable, based on the "filter object", and then return the IQueryable.
The so-called "filter object" is a System.Collections.Generic.List of an anonymous type of this structure: { column = fieldEnum, id = int }
The fieldEnum is an enum of the different columns of the Products table that I would possibly like to use for the filtering.
Instead of explaining further how my code works, it's easier if you just take a look at it. It's simple to follow.
enum filterType { supplier = 1, category }
public IQueryable<Product> getIQueryableProducts()
{
NorthwindDataClassesDataContext db = new NorthwindDataClassesDataContext();
IQueryable<Product> query = db.Products.AsQueryable();
//this section is just for the example. It creates a Generic List of an Anonymous Type
//with two objects. In real life I get the same kind of collection, but it isn't hard coded like here
var filter1 = new { column = filterType.supplier, id = 7 };
var filter2 = new { column = filterType.category, id = 3 };
var filterList = (new[] { filter1 }).ToList();
filterList.Add(filter2);
foreach(var oFilter in filterList)
{
switch (oFilter.column)
{
case filterType.supplier:
query = query.Where(p => p.SupplierID == oFilter.id);
break;
case filterType.category:
query = query.Where(p => p.CategoryID == oFilter.id);
break;
default:
break;
}
}
return query;
}
So here is an example. Let's say the List contains two items of this anonymous type, { column = fieldEnum.Supplier, id = 7 } and { column = fieldEnum.Category, id = 3}.
After running the code above, the underlying SQL query of the IQueryable object should contain:
WHERE SupplierID = 7 AND CategoryID = 3
But in reality, after the code runs the SQL that gets executed is
WHERE SupplierID = 3 AND CategoryID = 3
I tried defining query as a property and setting a breakpoint on the setter, thinking I could catch what's changing it when it shouldn't be. But everything was supposedly fine. So instead I just checked the underlying SQL after every command. I realized that the first Where runs fine, and query stays fine (meaning SupplierID = 7) until right after the foreach loop runs the second time. Right after oFilter becomes the second anonymous type item, and not the first, the 'query' SQL changes to Supplier = 3. So what must be happening here under-the-hood is that instead of just remembering that Supplier should equal 7, LINQ to SQL remembers that Supplier should equal oFilter.id. But oFilter is a name of a single item of a foreach loop, and it means something different after it iterates.
I have only glanced at your question, but I am 90% sure that you should read the first section of On lambdas, capture, and mutability (which includes links to 5 similar SO questions) and all will become clear.
The basic gist of it is that the variable oFilter in your example has been captured in the closure by reference and not by value. That means that once the loop finishes iterating, the variable's reference is to the last one, so the value as evaluated at lambda execution time is the final one as well.
The cure is to insert a new variable inside the foreach loop whose scope is only that iteration rather than the whole loop:
foreach(var oFilter in filterList)
{
var filter = oFilter; // add this
switch (oFilter.column) // this doesn't have to change, but can for consistency
{
case filterType.supplier:
query = query.Where(p => p.SupplierID == filter.id); // use `filter` here
break;
Now each closure is over a different filter variable that is declared anew inside of each loop, and your code will run as expected.
Working as designed. The issue you are confronting is the clash between lexical closure and mutable variables.
What you probably want to do is
foreach(var oFilter in filterList)
{
var o = oFilter;
switch (o.column)
{
case filterType.supplier:
query = query.Where(p => p.SupplierID == o.id);
break;
case filterType.category:
query = query.Where(p => p.CategoryID == o.id);
break;
default:
break;
}
}
When compiled to IL, the variable oFilter is declared once and used multiply. What you need is a variable declared separately for each use of that variable within a closure, which is what o is now there for.
While you're at it, get rid of that bastardized Hungarian notation :P.
I think this is the clearest explanation I've ever seen: http://blogs.msdn.com/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx:
Basically, the problem arises because we specify that the foreach loop is a syntactic sugar for
{
IEnumerator<int> e = ((IEnumerable<int>)values).GetEnumerator();
try
{
int m; // OUTSIDE THE ACTUAL LOOP
while(e.MoveNext())
{
m = (int)(int)e.Current;
funcs.Add(()=>m);
}
}
finally
{
if (e != null) ((IDisposable)e).Dispose();
}
}
If we specified that the expansion was
try
{
while(e.MoveNext())
{
int m; // INSIDE
m = (int)(int)e.Current;
funcs.Add(()=>m);
}
then the code would behave as expected.
The problem is that you're not appending to the query, you're replacing it each time through the foreach statement.
You want something like the PredicateBuilder - http://www.albahari.com/nutshell/predicatebuilder.aspx

Resources