使用LINQ在List中查找项目但获取“Value不能为null。 参数名称:source“

使用LINQ从列表中获取数据时遇到此错误。 怎么解决这个问题?

值不能为空。 参数名称: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)); } } 

执行后我得到的错误我的LINQ我得到了那种类型的结果(一行,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 >>>>

您收到的错误来自另一种方法,而不是您在此处显示的方法。 这是一个采用名称为“source”的参数的方法。 在“Visual Studio选项”对话框中,禁用“仅我的代码”,禁用“跳过属性和运算符”并启用“启用.NET Framework源步进”。 确保可以找到.NET符号。 然后调试器将在.NET方法内部破坏,如果它不是您自己的。 然后检查堆栈跟踪以查找传递的值为null,但不应该。

你应该寻找的是一个变为null并阻止它。 从查看代码,可能是itemsal.Add行中断。

编辑

由于你似乎在调试和LINQ方面遇到了麻烦,让我们一步一步地帮助你(也请注意上面扩展的第一部分,如果你还想以经典的方式尝试它,我还没有第一次完成周围):

  • 通过拆分代码缩小可能的错误情况;
  • 用故意不为null东西替换最终为null位置;
  • 如果全部失败,请将LINQ语句重写为循环并逐步完成。

步骤1

首先,通过将代码拆分为可管理的部分,使代码更具可读性:

 // 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 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) } } 

当然,上面的代码来自我的头脑,因为我不知道你有什么类型的类,因此无法在发布之前测试代码。 然而,如果你编辑它直到它是正确的(如果它不是开箱即用),那么你已经很有可能实际错误变得更加清晰。 如果没有,你至少应该看到一个不同的堆栈跟踪(我们仍然急切等待着!)。

第2步

下一步是精心替换可能导致空引用exception的每个部分。 我的意思是你替换这个:

 select new { SaleID = sale.OrderID, LineItem = GetLineItem(sale.LineItems) }; 

用这样的东西:

 select new { SaleID = 123, LineItem = GetLineItem(new LineItem(/*ctor params for empty lineitem here*/)) }; 

这将产生垃圾输出,但会将问题进一步缩小到您潜在的违规行。 对LINQ语句中可能最终为null (几乎所有内容)的其他位置执行与上面相同的操作。

第3步

这一步你必须自己做。 但是如果LINQ失败并且给你带来如此令人头疼的问题以及如此难以理解或难以调试的代码,那么考虑一下你遇到的下一个问题会发生什么? 如果它在现场环境中失败并且你必须在时间压力下解决它=

道德:学习新技术总是好的,但有时甚至更好地回到那些清晰易懂的东西。 没有什么可以对抗LINQ,我喜欢它,但在这种特殊情况下,让它rest,用一个简单的循环修复它,并在半年左右重新访问它。

结论

实际上,没有任何结论。 我走得更远,然后我通常会采用长期扩展的答案。 我希望它可以帮助您更好地解决问题,并为您提供一些工具,了解如何缩小难以调试的情况,即使没有高级调试技术(我们还没有讨论过)。

此exception可能指向名为source的LINQ参数:

  System.Linq.Enumerable.Select[TSource,TResult](IEnumerable`1 source, Func`2 selector) 

由于LINQ查询中的source参数( var nCounts = from sale in sal )是’ sal ‘,我认为名为’sal’的列表可能为null。

我认为如果您的数据库模型不正确并且基础数据包含模型试图映射到非null对象的null,则可能会出现此错误。

例如,某些自动生成的模型可以尝试将nvarchar(1)列映射到char而不是字符串,因此如果此列包含空值,则在尝试访问数据时会抛出错误。

注意,LinqPad有一个兼容性选项,如果你想要它生成这样的模型,但默认情况下可能不这样做,这可能解释它不会给你错误。

好的 – 我的情况与这个问题并没有严格的关系,但是当谷歌搜索相同的exception时我最终在这个页面上; 当我遇到这个exception时,我用LINQ查询了一个SQL数据库。

 private Table m_subscriptionsSql; var query = from SubscriptionModel subscription in m_subscriptionsSql ... 

原来我忘了初始化我在LINQ查询中使用的Table实例变量。

 m_subscriptionsSql = GetTable(); 

以下是更多将生成参数nullexception的代码示例:

 List myList = null; //from this point on, any linq statement you perform on myList will throw an argument null exception myList.ToList(); myList.GroupBy(m => m.Id); myList.Count(); myList.Where(m => m.Id == 0); myList.Select(m => m.Id == 0); //etc... 

此错误可能发生在多个位置, 最常见的是在null集合上运行进一步的LINQ查询 。 LINQ as Query Syntax看起来比它更安全。 请考虑以下示例:

 var filteredCollection = from item in getMyCollection() orderby item.ReportDate select item; 

此代码不是NULL SAFE,这意味着如果getMyCollection()返回null,您将获得Value cannot be null. Parameter name: source Value cannot be null. Parameter name: source错误。 很烦人! 但它非常有意义,因为LINQ Query语法只是这个等效代码的语法糖:

 var filteredCollection = getMyCollection().OrderBy(x => x.ReportDate); 

如果start方法返回null,那么显然会爆炸。

为了防止这种情况,您可以在LINQ查询中使用空合并运算符,如下所示:

 var filteredCollection = from item in getMyCollection() ?? Enumerable.Empty() orderby item.ReportDate select item; 

但是,您必须记住在任何相关查询中执行此操作。 最好的方法(如果你控制生成集合的代码)是使它成为一种编码实践,永远不会返回一个空集合,永远。 在某些情况下,从“ getCustomerById(string id) ”这样的方法返回一个null对象很好,这取决于你的团队编码风格,但如果你有一个返回业务对象集合的方法,比如“ getAllcustomers() ”那么它应该永远不会返回null数组/枚举/ etc。 始终始终使用if检查,null合并运算符或其他一些开关来返回空数组/列表/枚举等,以便您的方法的使用者可以自由地对结果进行LINQ。