Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using LINQ to find item in a List but get "Value cannot be null. Parameter name: source"

Tags:

c#

linq

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>>>>>

like image 649
Emaad Ali Avatar asked Jul 14 '10 08:07

Emaad Ali


2 Answers

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.

Edit

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):

  • Narrow down the possible error scenarios by splitting your code;
  • Replace locations that can end up null with something deliberately not null;
  • If all fails, rewrite your LINQ statement as loop and go through it step by step.

Step 1

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!).

Step 2

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).

Step 3

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.

Conclusion

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).

like image 116
Abel Avatar answered Oct 10 '22 23:10

Abel


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.

like image 21
wicky Avatar answered Oct 11 '22 01:10

wicky