调试复杂的 linq 查询
本文关键字:查询 linq 复杂 调试 | 更新日期: 2023-09-27 18:32:43
我正在处理一个复杂的linq
查询,如下所示,它在运行时引发System.NullReferenceException
。不幸的是,Visual Studio 不提供任何其他信息,我无法对值进行QuickWatch
以检查哪个值为空。有没有办法调试这种查询,以便我可以看到出了什么问题?
var dataSource = (from c in session.Query<PortChannel>()
select
new PortChannelData
{
Location = c.Port.MagazineSlot.SiteMagazine.Site.SiteName,
MagazineName =
String.Format("{0}-{1}", c.Port.MagazineSlot.SiteMagazine.MagazineType.MagazineName,
c.Port.MagazineSlot.SiteMagazine.MagazineNo),
SlotNo = c.Port.MagazineSlot.SlotNo,
PortNo = c.Port.PortNo,
Klm = c.Klm,
StmNo = c.StmNo,
Label = c.SiteName == null ? null : String.Format("{0}_{1}", c.SiteName, c.E1No),
ChannelFullName = c.ChannelFullName,
BscRncPort = c.BscRncPort,
MgwPort = c.MgwPort,
ReservedBy = c.ReservedBy,
CrossFullName = c.CrossConnection == null ? null : c.CrossConnection.ChannelFullName
}).ToList();
}
在查询中,可以使用 let
关键字来存储子表达式的结果。然后,在创建新的PortChannelData
对象时分配结果。
var dataSource =
(from c in session.Query<PortChannel>()
let flName = c.CrossConnection == null ? null : c.CrossConnection.ChannelFullName
let magName = String.Format("{0}-{1}", c.Port.MagazineSlot.SiteMagazine.MagazineType.MagazineName,
c.Port.MagazineSlot.SiteMagazine.MagazineNo)
// and so on
select new PortChannelData
{
MagazineName = magName,
CrossFullName = flName,
// ...
}).ToList();
这样,当您调试并单步执行查询(F11
是标准的 Visual Studio 快捷方式)时,您将看到每个子表达式的结果。
之前遇到过同样的问题,以下技术对我有很大帮助。
我已经将提取的值定义为select
表达式中的属性,并且在执行new ObjectName()
提取语句之前,这样当错误发生时,Visual Studio 会将我指向导致 null 引用的特定部分。
请考虑以下示例:
var returnNews = reportResult.Select(n =>
{
var createdBy = allUsersInfoForReport.FirstOrDefault(u => u.ID == n.CreatedBy);
var publishedBy = allUsersInfoForReport.FirstOrDefault(u => u.ID == n.Publishedby);
var modifiedBy = allUsersInfoForReport.FirstOrDefault(u => u.ID == n.LastModifiedBy);
newsViewCountEntity = newsViewCountCollection.FirstOrDefault(nv => nv.News_ID == n.ID);
newsCommentsCount = newsCommentsCollection.Count(s => s == n.ID);
return new ReportItemViewModel()
{
ID = n.ID,
AddedBy = createdBy != null ? createdBy.UserName : "",
UserSectionName = createdBy != null ? createdBy.RelatedSectionName : "",
PublishedBy = publishedBy != null ? publishedBy.UserName : "",
LastModifiedBy = modifiedBy != null ? modifiedBy.UserName : "",
}
});
在此示例中,如果以下任一属性 ( createdBy
- publishedBy
- modifiedBy
) 无法获取有效值,则会引发异常,但正确突出显示该行,而不是突出显示整个 LINQ 表达式。
尝试遵循相同的技术,并让我知道结果。
可以在new PortChannelData
行上放置断点并像往常一样进行调试(每次执行select语句时都会命中断点,即对于session.Query<PortChannel>()
中的每个元素)。
如果已将select
和new PortChannelData
放在同一行上,则设置断点会在 Linq 查询的开头放置断点。该断点仅在执行查询之前命中一次,并且不允许您"跳入"查询。但是,可以通过右键单击装订线中的红色断点点并选择"位置..."来更改 Visual Studio 中断点的位置。将位置设置为new PortChannelData
的起始行和字符,断点将放在 select 语句中。
还可以向断点添加条件,以便仅在满足条件时激活断点。如果session.Query<PortChannel>()
返回大量端口通道,则检查您正在访问的任何属性或字段是否为 null 的条件可以为您节省一些时间。