I have a list of objects as ICollection<objectA> listA. Now I'm trying to loop thru this listA and trying to match a condition and assign the result found into a variable. I tried below:
varB.someDesc = listA.FirstOrDefault(x=>x.ID == varB.ID).someDesc
Error complaining that x.ID is object null reference. When I put a break point, I can see there are many items in listA and there is an attribute ID. May I know what goes wrong?
I suggest validating the return value of FirstOrDefault() as follows:
var item = listA.FirstOrDefault(x=>x.ID == varB.ID);
if (item != null)
varB.someDesc = item.someDesc;
The error might not be exactly what you think it is.
Try this code.
varB.someDesc = listA.Where(x=>x.ID == varB.ID).FirstOrDefault().someDesc
you better check Object Null before assigning.
Related
I am confused. I have two statements that are the same and one works and the other receives the error - value cannot be null. r nparameter name source. From what I read I am receiving the error because something is null in my linq expression. However from what I can tell nothing is null.
The first if statement works. When a person selects 'Select' from a list of Burn Project a list of BurnPiles is displayed below the BurnProject list. (this works). Then when a person selects 'Select' from the list of BurnPiles a list of RequestedBurns is display below it. This gives me the null error. At one time it did work now it doesn't.
I am at a loss of what went wrong. I do know the RequestedBurn Table starts at record #2 but that shouldn't have anything to do with it. The BurnPile records that I have been using have associated RequestedBurns.
//when 'Select' is chosen from the list of burn projects the list of burn piles
//associated with that specific burn project is display below it.
if (burnerID != null)
{
ViewBag.BurnerID = burnerID.Value;
viewModel.BurnPiles = viewModel.BurnProjects.Where(
b => b.BurnerID == burnerID.Value).Single().BurnPiles;
}
//when 'Select' is chosen from the list of burn piles the list of requested
//burns associated with that specific burn pile is displayed below it.
if (burnPileID != null)
{
ViewBag.BurnPilesID = burnPileID.Value;
viewModel.RequestedBurns = viewModel.BurnPiles.Where(
x => x.BurnPilesID == burnPileID).Single().RequestedBurns;
}
If you look at documentation for Where or Single, you would see that source is the name of the parameter that represents your collection. So, it looks like you are trying to call a method on null reference, which would be the case if viewModel.BurnProjects = null or viewModel.BurnPiles = null.
viewModel.BurnPiles = viewModel.BurnProjects.Where(
b => b.BurnerID == burnerID.Value).Single().BurnPiles;
could be setting viewModel.BurnPiles to null.
or
viewModel.BurnPiles.Where(
x => x.BurnPilesID == burnPileID).Single()
is returning nothing so when you try and access RequestedBurns then it throws an exception.
SingleOrDefault also has an overload where you can simplify the expression a bit more. You can also combine it with the null conditional operator (if using at least C# 6).
if (burnerID != null)
{
ViewBag.BurnerID = burnerID.Value;
viewModel.BurnPiles = viewModel.BurnProjects.SingleOrDefault(b => b.BurnerID == burnerID.Value)?.BurnPiles;
}
For an invite function, I have a screen with a single field on it that lets users enter a code they've been given elsewhere. I then check in the controller to see which record is associated to this code. But my issue is with the controller blowing up if the code is not the first type is checks for (type 1 or type 2). So here what I believe it should be like(this doesn't work), although I realize the sloppiness I'm just new to c#.
Record rec = db.Records.Where(u = u.Code1).First();
If (rec != null)
{
Other code...
Exit controller
}
Record rec2 = db.Records.Where(u = u.Code2).First();
If (rec2 != null)
{
Other code...
Exit controller
}
Return to view - codes are invalid.
I've attempted other versions where I put the object check within the if statement but there didn't work either. Any ideas?
Use FirstOrDefault not First. First throws an exception if the collection is empty, FirstOrDefault returns default(T) if the collection is empty.
And actually, there are overloads of First and FirstOrDefault that take a condition parameter, so you don't need to call Where
ex:
var x = numbers.FirstOrDefault(n => n % 2 == 1);
This will return the first odd number in the collection, or 0 if there are none that meet the condition (or none at all.)
As explained by the MSDN docs on IEnumerable.First, this method throws an exception if there are no elements in the sequence
The First(IEnumerable) method throws an exception if
source contains no elements. To instead return a default value when
the source sequence is empty, use the FirstOrDefault method
So you should write
Record rec = db.Records.FirstOrDefault(u => u.Code1);
if(rec == null)
{
....
}
Notice that the same condition used in the Where extension could be used directly with FirstOrDefault
By the way, it is unclear what your expression is. The lambda expression (syntax is => ) should return a boolean value so, or your Code1 is a boolean variable or something is wrong in that line
Use db.Records.Where(u => u.Code1).FirstOrDefault();
Check the comparison value (ex. u.code1) if it has this property from the model before binding to the query.
I am too new to LINQ.
public static Dictionary<Type, ConfigurationObjectBase> MyDictionary;
This expression returns "Object reference not set to an instance of an object":
MyDictionary.First(o => o.Value.ID == 12).Key;
In fact, the object with ID = 12 is there.
Update:
In fact, the object with ID = 12 is there
it means, there is objects within dictionary where ID is 12.
If there were no such item, then it would throw InvalidOperationException with message "Sequence contains no matching element".
It means that either:
your Dictionary is not initialized. You said that there is an object with ID = 12. So, it means that is it initialized.
there is at least one item in your dictionary where a value is null. So, while iterating, it tries to access its Value.ID and throws a NullReferenceException.
Imagine a simple loop over an array:
ConfigurationObjectBase Search()
{
ConfigurationObjectBase[] array = { someObject1, someObject2, null, someObject3 };
foreach (var item in array)
{
if (item.ID == 12) return item;
// here, if item is null, you will try to access its ID and get NullReferenceException
}
throw new InvalidOperationException("Sequence contains no matching elements");
}
Actually, that's what LINQ exactly does. It iterates through the dictionary and once it tries to access a property of null, it throws an exception.
You may use the following code to avoid accessing the property of null:
MyDictionary.First(o => o.Value != null && o.Value.ID == 12).Key;
If there is an object with ID 12 it means that your dictionary contains objects which are null. You can filter for them:
MyDictionary.Where(x=>x.Value!=null).First(o => o.Value.ID == 12).Key;
It will skip all objects with null Value. I prefer chaining here, because it shows intention clearly.
EDIT:
as #Yeldar Kurmangaliyev said this answer is good only for small dictionaries. If you want to go with big dictionaries better do:
MyDictionary.First(o => o.Value!=null && o.Value.ID == 12).Key;
I have a LINQ query like so:
var Item = (from s in contextD.Items where s.Id == Id select s).ToList();
Further down the Item object properties are set like so:
Item.FirstOrDefault().Qty = qtyToUpdate;
Item.FirstOrDefault().TotalPrice = UItem.FirstOrDefault().Qty * UItem.FirstOrDefault().Price;
...
My question is, will calling FirstOrDefault always loop through the result set returned by the query?
Shouldn't a single call be made and put in an object like so:
MyObject objMyObject = new MyObject;
objMyObject = Item.FirstOrDefault();
and then go about setting objMyObject properties.
The first part using FirstOrDefault is actually in the production, I am trying to find out if that's the right way.
Regards.
will calling FirstOrDefault always loop through the result set
returned by the query?
FirstOrDefault() never loops through all result set - it either returns first item, or default if set is empty. Also in this particular case even enumerator will not be created - thus you are calling FirstOrDefault() on variable of List<T> type, simply item at index 0 will be returned (if list is not empty). If you will investigate Enumerable.FirstOrDefault() implementation:
IList<TSource> list = source as IList<TSource>;
if (list != null)
{
if (list.Count > 0)
{
return list[0];
}
}
But this will be invoked each time you are calling FirstOrDefault().
Also you are missing 'default' case. If you are chaining methods like in your first sample, you can get NullReferenceException if list is empty. So, make sure something was returned by query:
var item = Item.FirstOrDefault();
if (item == null)
return; // or throw
item.Qty = qtyToUpdate;
var uitem = UItem.FirstOrDefault();
if (uitem == null)
return; // or throw
item.TotalPrice = uitem.Qty * uitem.Price;
One more note - you have little difference in performance if you are performing FirstOrDefault() on in-memory collection. But difference will be huge if you will perform it without saving query results into list. In that case each FirstOrDefault() call will cause new database query.
Having some trouble with Predicates in C#.
I have two sets of code (Both of which I believe should accomplish the same result) but one never works. The reason I am asking is I need this predicate to appear a few times with different elements and so I'd like to keep it as minimal as possible (the non working one is very simplistic while the other contains many lines).
1 Not working:
ItemViewModel item = (App.ViewModel.All_Items.Where(x => (x as ItemViewModel).Name == my_list_of_strings.ElementAt(2)) as ItemViewModel);
Also using "Select" instead of Where isn't working.
2 Working:
foreach (ItemViewModel it in App.ViewModel.All_Items)
{
if (item.Name == my_list_of_strings.ElementAt(2))
{
MessageBox.Show("Success!!");
item = it;
continue; // Leave loop
}
}
It's probably something stupid that I've overlooked but if anyone knows the solution, that would be great!
Thanks.
IEnumerable<T>.Where(Func<T, bool>) returns a collection however it looks like what you want is a single element. There are a couple of options:
IEnumerable<T>.FirstOrDefault(Func<T, bool>) // returns null if no element found
IEnumerable<T>.First(Func<T, bool>) // throws if no element is found
// These throw an error if more than one element exists that matches the query
IEnumerable<T>.SingleOrDefault(Func<T, bool>) // returns null if no element found
IEnumerable<T>.Single(Func<T, bool>) // throws if no element is found
In your example it would be:
// Just replace "Where" with "FirstOrDefault"
ItemViewModel item = (App.ViewModel.All_Items.FirstOrDefault(x => (x as ItemViewModel).Name == my_list_of_strings.ElementAt(2)) as ItemViewModel);