Linq帮助-子查询给出空指针异常

本文关键字:空指针异常 查询 帮助 Linq | 更新日期: 2023-09-27 18:00:59

我编写了一个电子邮件系统,其中有一个用户表"tblUsers"和一个消息表。用户的收件箱中可以有许多邮件(来自tblusers中的其他用户((一封:多封(。

在tblUsers表中,我有一个名为ImageURL(字符串(的列,其中包含用户化身的URL。在这种情况下,我正在循环浏览属于用户的收件箱中的消息,我要做的是,一旦我收到消息,就沿着树走到tblUser,并在ImageURL列中获得该消息所有者的值,标记为下面的"SenderAvatar"。

这是我试过的。问题是,下面SenderAvatar的子linq抛出了一个null指针异常,尽管我已经确认ImageURL有一个值(这是dev,所以只有三个用户(。不知怎么的,我的逻辑和林的逻辑在这里不一致。有人能帮忙吗?谢谢

编辑我发现了两个虫子。第一个错误是Dzienny,它让我找到了比较苹果和橙子的正确方向。第二个错误是FromUserId = ux.tblUserId,,我将当前用户id设置为FromUserId Guys,感谢您在这方面的帮助。

 public List<UserInboxMsg> GetUserInboxMsg(IKASLWSEntities conx, int userid)
    {
        var u = (from m in conx.tblUsers where m.Id == userid select m).FirstOrDefault();
        if (u != null)
        {
            return (from ux in u.tblInboxes
                    orderby ux.CreationTS descending
                    select new UserInboxMsg
                    {
                        CreationTS = ux.CreationTS,
                        ExpirationDate = ux.ExpirationDate,
                        FromUserId = ux.tblUserId,
                        HasImage = ux.HasImage,
                        ImageId = ux.ImageId ?? 0,
                        IsDeleted = ux.IsDeleted,
                        IsRead = ux.IsRead,
                        MsgId = ux.Id,
                        MsgSize = ux.MessageSize,
                        ParentId = ux.ParentId,
                        Title = ux.Title,
                        ToUserId = userid,
                        FromUserName = ux.Title,
                        SenderAvatar = conx.tblMessages.Where(mu=>mu.Id == ux.Id).FirstOrDefault().tblUser.ImageURL,
                        Message = ux.Message
                    }).ToList<UserInboxMsg>();
        }
        else
        {
            return new List<UserInboxMsg>();
        }
    }
}

Linq帮助-子查询给出空指针异常

如果在实体框架中,两个表之间存在外键引用,您可能会这样做:

SenderAvatar = conx.tblMessages.FirstOrDefault( mu=>mu.Id == ux.Id).ImageURL,

试试这个。

   public List<UserInboxMsg> GetUserInboxMsg(IKASLWSEntities conx, int userid)
        {
            var u = (from m in conx.tblUsers where m.Id == userid select m).FirstOrDefault();
            if (u != null && conx != null)
        {
            return (from ux in u.tblInboxes
                    orderby ux.CreationTS descending
                    select new UserInboxMsg
                    {
                        ...
                        ...
                        SenderAvatar = conx.tblMessages.Any(mu=>mu.Id == ux.Id) ? (conx.tblMessages.First(mu=>mu.Id == ux.Id).tblUser != null? conx.tblMessages.First(mu=>mu.Id == ux.Id).tblUser.ImageURL : null) : null,
                        Message = ux.Message
                    }).ToList<UserInboxMsg>();
        }
        else
        {
            return new List<UserInboxMsg>();
        }
    }
}

如果Avatar为null,要么是因为tblMessages中没有mu.Id等于ux的条目。Id或tblMessage条目存在,但tblUser属性为空

这里有几个问题。

第一个是第二条语句在内存中执行,而可以使整个查询以SQL:的形式运行

from u in conx.tblUsers where m.Id == userid
from ux in u.tblInboxes
orderby ux.CreationTS descending
select new UserInboxMsg
{
    CreationTS = ux.CreationTS,
    ExpirationDate = ux.ExpirationDate,
    FromUserId = ux.tblUserId,
    HasImage = ux.HasImage,
    ImageId = ux.ImageId ?? 0,
    IsDeleted = ux.IsDeleted,
    IsRead = ux.IsRead,
    MsgId = ux.Id,
    MsgSize = ux.MessageSize,
    ParentId = ux.ParentId,
    Title = ux.Title,
    ToUserId = userid,
    FromUserName = ux.Title,
    SenderAvatar = conx.tblMessages.Where(mu => mu.Id == ux.Id)
                       .FirstOrDefault().tblUser.ImageURL,
    Message = ux.Message
}

这有三个好处:

  • 从数据库中提取的数据较少
  • 您可以消除null引用异常,因为SQL没有null引用。如果找不到记录,它只返回null
  • 您可以在不使用if-else的情况下返回此语句的结果

其次,不太重要的是,您应该使用像Inbox.Messages这样的导航属性,而不是加入(某种程度上(收件箱及其消息。这使得您不太可能使用错误的联接变量,并且它浓缩了您的代码:

SenderAvatar = ux.Messages.
                 .FirstOrDefault().User.ImageURL,

现在,如果没有化身,就是没有化身。并且不存在空引用异常。

(顺便说一句,你可以看到我讨厌类和属性名称中的这些前缀(。

我只能猜测您的代码的这一部分是错误的:SenderAvatar = conx.tblMessages.Where(mu=>mu.Id == ux.Id).FirstOrDefault().tblUser.ImageURL例如,我认为您应该使用(mu=>mu.UserId==ux.Id(而不是。(仅适用于一对一关系(

我说我可以猜,因为你没有提到任何关于tblInboxestblMessages字段的信息。如果你能提供更多关于它们结构的信息,我可以更详细地回答。

顺便说一下,为了使代码更加清晰,您可以使用:

var u = conx.tblUsers.FirstOrDefault(m=>m.Id == userid);

而不是

var u = (from m in conx.tblUsers where m.Id == userid select m).FirstOrDefault();

conx.tblMessages.FirstOrDefault(mu=>mu.Id == ux.Id)

而不是

conx.tblMessages.Where(mu=>mu.Id == ux.Id).FirstOrDefault()