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>();
}
}
}
如果在实体框架中,两个表之间存在外键引用,您可能会这样做:
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(而不是。(仅适用于一对一关系(
我说我可以猜,因为你没有提到任何关于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();
或
conx.tblMessages.FirstOrDefault(mu=>mu.Id == ux.Id)
而不是
conx.tblMessages.Where(mu=>mu.Id == ux.Id).FirstOrDefault()