List.Where(“ string” .Contains())在LINQ查询中返回NULL

时间:2019-12-06 00:10:22

标签: c# .net entity-framework linq

我的Product班:

public class Product {
 public int Id { get; set; }
 public string NameEnglish { get; set; }
 public string NameItalian { get; set; }
}

我的Language班:

public class Language{
  public int Id { get; set; }
  public string LanguageType { get; set; }
}

,我有一种方法可以使用“名称”属性搜索“产品”并返回List<Product>

List<Product> GetProductsFromSearch(int languageId, string searchedData){
    var products = _contex.Products.ToList();
    switch(languageId) //LanguageId 1 = English , LangaugeId 2 = Italian
    {
       case 1:
            return products.Where(i=>i.NameEnglish.Contains(searchedData)).ToList();
       case 2:
            return products.Where(i=>i.NameItalian.Contains(searchedData)).ToList();
       default:
            return products;
    }
}

问题在于,某些产品的“英语”或“意大利语”名称字段尚未在Db中分配,因此这些字段为 null 字段。

程序给出错误“对象引用未设置为对象的实例”。

所以我添加了一个额外的控件:

return products.Where(i=> !string.isNullOrEmpty(i.NameEnglish) && 

                          i.NameEnglish.Contains(searchedData)).ToList()

但是我仍然遇到相同的错误。有人可以帮忙吗?我感到困惑,是不是应该通过 字段?

注意:  我知道我应该直接在_context.Products.Where(i=>i.NameEnglish.Contains(searchedData)).ToList();中进行过滤 但这是出于我的 test 目的,我正尝试在“列表”类型中使用“位置”。

Id | NameEnglish | NameItalian
1  | Ball        | Palla
2  | Phone       | Telefono
3  | Tshirt      | NULL
4  | NULL        | Bicchiere

注意::我现在有12行,现在有4行。(它并没有改变结果,但是我已经删除了,以便您清楚地看到我的表格)

5 个答案:

答案 0 :(得分:6)

如果所有这些项目确实为空,则可以使用空条件运算符。它比空检查更干净,IMO:

products.Where(p => p.NameEnglish?.Contains(searchedData) == true);

NameItalian类似。

答案 1 :(得分:1)

尝试以下操作:

List<Product> GetProductsFromSearch(int languageId, string searchedData){
   if (string.IsNullOrEmpty(searchedData))
       return new List<Product>();

   var query = _contex.Products; 

    switch(languageId) //LanguageId 1 = English , LangaugeId 2 = Italian
    {
       case 1:
            query = query.Where(i=>i.NameEnglish.Contains(searchedData));
       case 2:
            query = query.Where(i=>i.NameItalian.Contains(searchedData));
    }

    return query.ToList();
}

如果这引发错误,请提供确切的异常详细信息和任何内部异常。上面的方法应该可以工作,并且当传递给EF2SQL时,应该可以处理名称为空的可能性。

如前所述,您想从列表中加载。在这种情况下,您需要声明null检查:

List<Product> GetProductsFromSearch(int languageId, string searchedData){
   if (string.IsNullOrEmpty(searchedData))
       return new List<Product>();

   var query = _contex.Products.ToList(); 

    switch(languageId) //LanguageId 1 = English , LangaugeId 2 = Italian
    {
       case 1:
            query = query.Where(i=> !string.IsNullOrEmpty(i.NameEnglish) && i.NameEnglish.Contains(searchedData));
       case 2:
            query = query.Where(i=> !string.IsNullOrEmpty(i.NameItalian) && i.NameItalian.Contains(searchedData));
    }

    return query.ToList();
}

我怀疑如果您键入错误/复制粘贴问题,并针对另一种语言的错误名称值进行了空检查,则您的尝试可能会失败。即IsNullOrEmpty对应英文名称,但Contains对应意大利名称。

答案 2 :(得分:0)

尝试i=>i.NameItalian != null && i.NameItalian.Contains(searchedData),英语也同样。

答案 3 :(得分:0)

我建议将记录器添加到您的上下文中只是出于调试目的:

https://docs.microsoft.com/en-us/ef/ef6/fundamentals/logging-and-interception

然后,您可以查看生成了哪些确切查询以及哪个确切查询导致了问题。有时,对sql的翻译并不完全像您想的那样。

答案 4 :(得分:0)

这归结为一个简单的因素。您必须了解分配逻辑的流程。 NPE总是处理可变分配,这可能有几个原因。 Linq作为Any(),可以用来在IEnumerable上测试条件之前必须提取其结果。这可以帮助您为该异常配备适当的句柄。