C# LINQ查询中的WHERE子句似乎失败
请原谅我的天真,我对C#的世界是全新的。如果我遗漏了有用的信息,请告诉我 我正在为Dynamics CRM 2011的客户门户构建自定义SiteMapProvider。首先,我初始化一个数组:C# LINQ查询中的WHERE子句似乎失败,c#,linq,dynamics-crm-2011,sitemapprovider,C#,Linq,Dynamics Crm 2011,Sitemapprovider,请原谅我的天真,我对C#的世界是全新的。如果我遗漏了有用的信息,请告诉我 我正在为Dynamics CRM 2011的客户门户构建自定义SiteMapProvider。首先,我初始化一个数组: public Adx_webpage[] WebPages; 这就让人觉得: public MyProvider() { WebPages = (FROM p in CrmContext.Adx_webpageSet WHERE p.Adx_HiddenFromSitemap != true S
public Adx_webpage[] WebPages;
这就让人觉得:
public MyProvider()
{
WebPages = (FROM p in CrmContext.Adx_webpageSet WHERE p.Adx_HiddenFromSitemap != true SELECT p).ToArray();
}
稍后,我尝试查询网页[],如下所示:
Adx_webpage[] childPages = (FROM p in WebPages WHERE p.adx_parentpageid.Id == page.Id SELECT p).ToArray();
当我通过调试器运行它时,我得到一个NullReferenceException,它指向WHERE子句中的条件,指出p.adx_parentpageid.Id为null,这对于站点的主页是真的。这就引出了一个问题:
为什么此查询会在我的查询中将主页显示为p
?我误解了什么?问题在于您第一次查询时的.ToArray()。此linq查询正在为您的CrmContext提供程序创建本机查询:
WebPages = (FROM p in CrmContext.Adx_webpageSet WHERE p.Adx_HiddenFromSitemap != true SELECT p).ToArray();
.ToArray()导致linq查询立即运行并返回一个普通的旧对象数组。数组未附加到CrmContext对象
但是,此查询使用Linq to Objects对第一次调用中返回的数组进行迭代。它不是为您的CrmContext提供程序生成本机查询
Adx_webpage[] childPages = (FROM p in WebPages WHERE p.adx_parentpageid.Id == page.Id SELECT p).ToArray());
这实际上与使用foreach循环迭代数组中的每个元素相同,因此您必须担心检查第一次查询返回的可能的空值。我不理解您的问题。你是说主页是一个网页,它不会从网站地图中隐藏,那么为什么你不希望主页在你的查询中显示为
p
无论如何,您可以简单地跳过p==null
的任何内容:
Adx_webpage[] childPages = (FROM p in WebPages
WHERE p.adx_parentpageid != null &&
p.adx_parentpageid.Id == page.Id
SELECT p).ToArray();
你的第一行
WebPages = (FROM p in CrmContext.Adx_webpageSet WHERE p.Adx_HiddenFromSitemap != true SELECT p).ToArray();
将返回站点地图中未隐藏的所有页面。但这也包括没有父id的主页。因此,当第二个查询在此集合上枚举时,它将尝试访问此null属性并引发null引用异常。您只需要在查询中考虑到这一点
Adx_webpage[] childPages =
(FROM p in WebPages WHERE
p.adx_parentpageid.Id != null &&
p.adx_parentpageid.Id == page.Id SELECT p).ToArray();
您是否懒得加载实体?如果子对象都为空,则可能需要加载它们。主页是否从站点地图中隐藏?p.adx_parentpageid.Id的数据类型是什么?我认为它实际上是p.adx_parentpageid,它是空的,并且它与您一起抛出,试图访问Id属性。如果p.adx_parentpageid可以为空,则需要为该条件编写代码。@JonC-我不知道什么是“延迟加载”。@saturdayplace抱歉,我没有添加更多信息。之前这里有一篇文章专门针对CRM 2011讨论这一点,好的,这很有意义。我只想访问数据库一次,这就是为什么我要进行第一次查询以获取数据库中的所有页面,然后再查询生成的数组;林克似乎对此很有意义。有更好的方法吗?Linq to Objects就可以了。您只需要记住,它只是在下面运行.net代码,并且不会像本机查询那样屏蔽空引用。如果一个对象没有关系,它不会被简单地排除,它会抛出一个空引用异常。