C# 调试复杂的linq查询
我正在处理一个复杂的C# 调试复杂的linq查询,c#,linq,debugging,visual-studio-2013,C#,Linq,Debugging,Visual Studio 2013,我正在处理一个复杂的linq查询,如下所示,它在运行时引发System.NullReferenceException。不幸的是,visual studio没有提供任何其他信息,我无法对值执行QuickWatch,以检查哪个值为空。有没有一种方法可以调试这种查询,这样我就可以看到哪里出了问题 var dataSource = (from c in session.Query<PortChannel>() select new PortChanne
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();
}
var dataSource=(来自session.Query()中的c)
选择
新PortChannelData
{
位置=c.Port.MagazineSlot.SiteMagazine.Site.SiteName,
马加齐尼奈=
String.Format(“{0}-{1}”),c.Port.MagazineSlot.SiteMagazine.MagazineType.MagazineName,
c、 Port.MagazineSlot.SiteMagazine.MagazineNo),
SlotNo=c.Port.MagazineSlot.SlotNo,
端口号=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();
}
我以前也遇到过同样的问题,下面的技术对我帮助很大
我已将提取的值定义为我的select
表达式中的属性,在执行new ObjectName()
提取语句之前,这样,当发生错误时,visual studio会将我指向导致空引用的特定部分
考虑以下示例:
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表达式
尝试使用相同的技术,并让我知道结果。您可以在
新PortChannelData
行上放置一个断点,并像往常一样进行调试(每次执行select语句时,即针对会话.Query()中的每个元素,都会命中断点)
如果将select
和newportchanneldata
放在同一行上,则设置断点将在Linq查询的开始处设置断点。该断点仅在执行查询之前命中一次,并且不允许您“跳入”查询。但是,您可以在Visual Studio中更改断点的位置,方法是右键单击边沟中的红色断点点并选择“位置…”。将位置设置为newportchanneldata
的起始行和字符,断点将放在select语句中
您还可以向断点添加条件,使其仅在满足条件时激活。如果session.Query()
返回大量端口通道,则检查正在访问的任何属性或字段是否为空的条件可以节省一些时间。在查询中,可以使用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();
var数据源=
(来自session.Query()中的c)
让flName=c.CrossConnection==null?null:c.CrossConnection.ChannelFullName
让magName=String.Format(“{0}-{1}”),c.Port.MagazineSlot.SiteMagazine.MagazineType.MagazineName,
c、 Port.MagazineSlot.SiteMagazine.MagazineNo)
//等等
选择新端口通道数据
{
MagazineName=magName,
CrossFullName=flName,
// ...
}).ToList();
这样,当您调试并进入查询(F11
是标准的Visual Studio快捷方式)时,您将看到每个子表达式的结果。您尝试过吗?@Luca Nope我将查看它,谢谢!这个LINQ查询几乎没有什么复杂之处请注意在查询结束时的.ToList()调用-这会覆盖延迟执行,允许您单步执行代码(有关更多信息,请参阅:),因此即使在复杂的LINQ查询中也常常忘记F11