【问题标题】:String comparison throws null reference exception字符串比较抛出空引用异常
【发布时间】:2012-08-19 20:57:27
【问题描述】:

我正在尝试在我的数据库中查找用户,搜索电子邮件和电话号码。 但是,如果我使用 List 或 IEnumerable 我会得到一个空引用异常。如果我不使用其中任何一个,则会抛出“不支持 SQL ...”。

我的方法:

public List<tblMember> getAllMembers()
{
    return db.tblMembers.ToList();
}

private void confirmMembership(string email, int phoneNumber)
{
    //var allMembers = db.tblMembers.AsEnumerable(); throws same exception
    tblMember member = getAllMembers().FirstOrDefault(x => x.email.Equals(email, StringComparison.OrdinalIgnoreCase) && x.phoneNumber == phoneNumber); //This line throws exception, around email.Equals()
    if (member != null)
    {
        member.isConfirmed = true;
        db.SubmitChanges();
    }
    else
        throw new Exception("Member not found");
}

如果我这样执行搜索,不会抛出异常:

private void confirmMembership(string email, int phoneNumber)
{
    //var allMembers = db.tblMembers.AsEnumerable(); throws same exception
    tblMember member = getAllMembers().FirstOrDefault(x => x.email == email && x.phoneNumber == phoneNumber);
    if (member != null)
    {
        member.isConfirmed = true;
        db.SubmitChanges();
    }
    else
        throw new Exception("Member not found");
}

这怎么可能?

【问题讨论】:

    标签: c# linq linq-to-sql compare


    【解决方案1】:

    在第一种情况下,您在一个为 null 的对象上调用 Equals()。

    x.email.Equals(...)
    

    这会引发异常。

    在第二种情况下,您正在比较两件事,其中一件可能为空

    x.email == email
    

    这是基于 cmets 的最新版本:

    private void confirmMembership(string email, int phoneNumber)
    {
        tblMember member = tblMembers.FirstOrDefault((x) => {
            if (x.email == null)  return false;
            return SqlMethods.Like(x.email,email) && x.phoneNumber == phoneNumber); 
          }
        if (member != null)
        {
            member.isConfirmed = true;
            db.SubmitChanges();
        }
        else
            throw new Exception("Member not found");
    }
    

    这是另一种不会抛出异常的方法:

    private void confirmMembership(string email, int phoneNumber)
    {
        //var allMembers = db.tblMembers.AsEnumerable(); throws same exception
        tblMember member = getAllMembers().FirstOrDefault((x) => {
            if (x.email == null)  return false;
            return x.email.Equals(email, StringComparison.OrdinalIgnoreCase) && x.phoneNumber == phoneNumber); 
          }
        if (member != null)
        {
            member.isConfirmed = true;
            db.SubmitChanges();
        }
        else
            throw new Exception("Member not found");
    }
    

    【讨论】:

    • 所以如果 email 只是一行的 null 就会抛出异常?
    • 如我的回答中所述,此处显示的语句 lambda 不能转换为表达式树。
    • @JonSkeet 我只将 x.email != null 添加到我的代码中,因为参数 email 永远不会为空。
    • @KLIM8D:没错,这就是我所希望的。我没有注意到您在此之前已经调用了ToList,因此表达式树转换的问题无关紧要,尽管我仍然会根据我的回答使用复合形式。
    • @KLIM8D:请重新阅读我现在编辑的答案;我之前没有发现您正在查询List&lt;T&gt;。我强烈建议您将过滤转移到数据库中 - 每次您想找到一个成员时获取整个表,一旦您有很多成员,就会执行可怕
    【解决方案2】:

    这可能是因为x.email 为空。如果为 null,则调用它的成员会引发异常。

    x.email.Equals(...)   ==> exception
    

    但是,您可以比较两个可能为空的值

    x.email == email      ==> OK.
    

    【讨论】:

      【解决方案3】:

      我怀疑这是因为 x.email 对于某些 x 值是空的。

      试试:

      tblMember member = db.tblMembers
           .FirstOrDefault(x => x.email != null
                           && x.email.Equals(email, StringComparison.OrdinalIgnoreCase) 
                           && x.phoneNumber == phoneNumber);
      

      编辑:我刚刚注意到 getAllMembers() 返回一个 List&lt;T&gt; 所以你不必担心我之前谈到的表达式树转换 - 但你当前的代码正在获取 all 每次调用此方法时从数据库中获取数据。你真的想要吗?我上面提供的代码将在数据库中进行过滤,这肯定是您感兴趣的。

      【讨论】:

      • 我认为如果参数email作为null传入,这将失败。在这种情况下,您希望它只匹配电话号码。
      • @Hogan:在这种情况下,我实际上希望它对所有值都失败。目前尚不清楚 OP 是否希望匹配表中存在空电子邮件地址的第一个值。 (我希望该参数实际上是不可为空的,应该在方法开始时对其进行验证。)
      • 当然,除了他给出的不使用 OrdinalIgnoreCase 的示例将按照我描述的那样执行。我想我是从表面上看要求的。
      • @Hogan:实际上我不确定它表现得像那样。这取决于所使用的 SQL 翻译,但我见过 LINQ 场景,您必须明确地说 (x.email == null &amp;&amp; email == null) || x.email == email 才能匹配 NULL==NULL。
      • @KLIM8D:好的,所以您需要告诉我们您使用的是 LINQ to SQL 还是 Entity Framework,我们可以进一步帮助您。在每次调用时将整个表拉入内存确实不是一个好的长期解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 2010-10-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-16
      • 2021-04-29
      • 2022-01-05
      相关资源
      最近更新 更多