When using LINQ to get data from a list I encounter this error. How can this be fixed?
Value cannot be null. Parameter name: source
var nCounts = from sale in sal select new { SaleID = sale.OrderID, LineItem = from sli in sale.LineItems group sli by sli.Item into ItemGroup select new { Item = ItemGroup.Key, Weeks = ItemGroup.Select(s => s.Week) } }; foreach (var item in nCounts) { foreach (var itmss in item.LineItem) { // MessageBox.Show(itmss.Item.Name); itemsal.Add(new Roundsman.BAL.WeeklyStockList(itmss.Item.Name.ToString(), itmss.Item.Code.ToString(), itmss.Item.Description.ToString(), Convert.ToInt32(itmss.Item.Quantity), 2, 2, 2, 2, 2, 2, 2, 2, 2)); } }
Error which i got after execution my LINQ I got that type of result (one line, orginally):
System.Linq.Enumerable.WhereSelectListIterator<Roundsman.BAL.Sale, <>f__AnonymousType1<int,System.Collections.Generic.IEnumerable <<>f__AnonymousType0<Roundsman.BAL.Items.Item,System.Collections.Generic.IEnumerable <Roundsman.BAL.WeeklyRecord>>>>>
The error you receive is from another method than the one you show here. It's a method that takes a parameter with the name "source". In your Visual Studio Options dialog, disable "Just my code", disable "Step over properties and operators" and enable "Enable .NET Framework source stepping". Make sure the .NET symbols can be found. Then the debugger will break inside the .NET method if it isn't your own. then check the stacktrace to find which value is passed that's null, but shouldn't.
What you should look for is a value that becomes null
and prevent that. From looking at your code, it may be the itemsal.Add
line that breaks.
Since you seem to have trouble with debugging in general and LINQ especially, let's try to help you out step by step (also note the expanded first section above if you still want to try it the classic way, I wasn't complete the first time around):
null
with something deliberately not null
;First make the code a bit more readable by splitting it in manageable pieces:
// in your using-section, add this: using Roundsman.BAL; // keep this in your normal location var nCounts = from sale in sal select new { SaleID = sale.OrderID, LineItem = GetLineItem(sale.LineItems) }; foreach (var item in nCounts) { foreach (var itmss in item.LineItem) { itemsal.Add(CreateWeeklyStockList(itmss)); } } // add this as method somewhere WeeklyStockList CreateWeeklyStockList(LineItem lineItem) { string name = itmss.Item.Name.ToString(); // isn't Name already a string? string code = itmss.Item.Code.ToString(); // isn't Code already a string? string description = itmss.Item.Description.ToString(); // isn't Description already a string? int quantity = Convert.ToInt32(itmss.Item.Quantity); // wouldn't (int) or "as int" be enough? return new WeeklyStockList( name, code, description, quantity, 2, 2, 2, 2, 2, 2, 2, 2, 2 ); } // also add this as a method LineItem GetLineItem(IEnumerable<LineItem> lineItems) { // add a null-check if(lineItems == null) throw new ArgumentNullException("lineItems", "Argument cannot be null!"); // your original code from sli in lineItems group sli by sli.Item into ItemGroup select new { Item = ItemGroup.Key, Weeks = ItemGroup.Select(s => s.Week) } }
The code above is from the top of my head, of course, because I cannot know what type of classes you have and thus cannot test the code before posting. Nevertheless, if you edit it until it is correct (if it isn't so out of the box), then you already stand a large chance the actual error becomes a lot clearer. If not, you should at the very least see a different stacktrace this time (which we still eagerly await!).
The next step is to meticulously replace each part that can result in a null reference exception. By that I mean that you replace this:
select new { SaleID = sale.OrderID, LineItem = GetLineItem(sale.LineItems) };
with something like this:
select new { SaleID = 123, LineItem = GetLineItem(new LineItem(/*ctor params for empty lineitem here*/)) };
This will create rubbish output, but will narrow the problem down even further to your potential offending line. Do the same as above for other places in the LINQ statements that can end up null
(just about everything).
This step you'll have to do yourself. But if LINQ fails and gives you such headaches and such unreadable or hard-to-debug code, consider what would happen with the next problem you encounter? And what if it fails on a live environment and you have to solve it under time pressure=
The moral: it's always good to learn new techniques, but sometimes it's even better to grab back to something that's clear and understandable. Nothing against LINQ, I love it, but in this particular case, let it rest, fix it with a simple loop and revisit it in half a year or so.
Actually, nothing to conclude. I went a bit further then I'd normally go with the long-extended answer. I just hope it helps you tackling the problem better and gives you some tools understand how you can narrow down hard-to-debug situations, even without advanced debugging techniques (which we haven't discussed).
This exception could point to the LINQ parameter that is named source:
System.Linq.Enumerable.Select[TSource,TResult](IEnumerable`1 source, Func`2 selector)
As the source
parameter in your LINQ
query (var nCounts = from sale in sal
) is 'sal
', I suppose the list named 'sal' might be null.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With