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

时间:2015-07-04 17:26:22

标签: c# linq entity-framework subquery

我在写一个电子邮件系统,我们有一个用户表" tblUsers"和一张消息表。用户可以在他或她的收件箱中收到许多消息(来自tblusers中的其他用户)(一个:多个)。

在tblUsers表中,我有一个名为ImageURL(string)的列,其中包含用户头像的URL。在这种情况下,我循环浏览属于用户的收件箱中的邮件以及我尝试做的是,一旦收到邮件,将树向上走到tblUser并获取值该邮件所有者的ImageURL列标记为" SenderAvatar"下面。

这是我尝试过的。问题是,下面的SenderAvatar的sub linq抛出了一个nullpointer异常,即使我已经确认ImageURL有一个值(这是dev,所以只有三个用户)。不知怎的,我的逻辑和linq的逻辑在这里不一致。有人可以帮忙吗?谢谢!

修改 我发现了两个漏洞。第一个错误Dzienny指出了我正在比较苹果和橙子的正确方向。第二个错误是FromUserId = ux.tblUserId,,我将当前用户ID设置为FromUserId个人,感谢您对此的所有帮助。

 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>();
        }
    }

}

4 个答案:

答案 0 :(得分:1)

试试这个。

   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属性为null

答案 1 :(得分:1)

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

"allFrames": true

答案 2 :(得分:1)

这里有几个问题。

第一个是第二个语句在内存中执行,而可以使整个查询以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
}

这有三个好处:

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

其次,不太重要的是,您应该使用Inbox.Messages之类的导航属性,而不是加入(排序)收件箱及其消息。这使得您使用错误的连接变量的可能性降低,并且会压缩您的代码:

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

现在如果没有头像,那么 没有头像。并且没有空引用异常。

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

答案 3 :(得分:1)

我只能猜测你的代码部分是错误的:SenderAvatar = conx.tblMessages.Where(mu=>mu.Id == ux.Id).FirstOrDefault().tblUser.ImageURL 我想你应该使用(mu =&gt; mu.UserId == ux.Id)而不是(mu =&gt; mu.Id == ux.Id)。在您的代码中,您将表的“Id”与另一个表的“Id”进行比较,该表通常在一对多关系中是错误的。 (仅适用于一对一的关系)

我说我可以猜到,因为您没有提及有关 tblInboxes tblMessages 字段的任何信息。如果您可以向我提供有关其结构的更多信息,我可以更详细地回答。

顺便提一下您的代码可以使用:

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

而不是

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

OR

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

而不是

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