1

我正在尝试获取一个列表的项目,其中任何多重查找值都包含在另一个查询的结果中。

情况是这样的:我正在构建一个 web 部件,用户可以使用它使用一组共享点(foundation 2010)列表为五个属性下拉列表制作报告(“融合”)。这些属性通过列表中的查找进行连接。每次更改下拉选择时,都会发生回发并重新填充以下下拉列表。

问题是属性之间的连接不是与下拉列表的直接匹配。这是因为下拉输入被选择用于报表的直观输入,并且数据模型被设计为系统数据的简单和直观输入,而不是为了高效和简单的编程......

数据模型的相关部分:
-Locaties(位置)是一个列表 -Contracten
(合同)是一个列表,每个合同都有一个或多个位置(多查找)
-Urgentie(紧急度)是一个列表,每个紧急有一个合同(lookup)
-Meldingtypes (reporttype) 是一个列表 -Categorieën
(categories) 是一个列表,每个类别有一个 meldingtype (lookup),每个类别有一个或多个合约 (multi-lookup)

报告输入如下:
用户首先选择Locatie
用户选择Meldingtype 第二
用户选择Categorie 第三
用户选择Contract 第四
最后用户选择Urgentie

当然,每次下拉菜单都应该只填充有效的选项。So when a location is chosen, the only meldingtypes shown in the dropdown should be the ones that have categories which have a contract which have the chosen location...yeah, I know ;)

我在创建查询以填充下拉列表时遇到问题。我一直在尝试几种方法,包括多个查询、使用 Contains 选择器的构造,但都没有奏效。在上一次迭代中,我创建了一个查询,该查询使用一个项目在被多重查找引用时所具有的属性。这是 meldingtype 下拉列表的示例:

    private void fillMeldingtypeDropdown(Intermediair.IntermediairDataContext idctx)
    {
        var meldingtypeData = (from l in idctx.Locaties
                               from co in l.ContractenItem
                               from ca in co.CategorieënItem
                               where l.Id == selectedLocatieId
                               select ca.Meldingtype
                              ).Distinct<Intermediair.Item>();
        foreach (Intermediair.Item meldingtype in meldingtypeData)
        {
            ctrl_Meldingtype.Items.Add(new ListItem(meldingtype.Titel, meldingtype.Id.ToString()));
        }
    }

selectedLocatieId 是一个从 Locatie 下拉控件中获取值的属性。

上面的代码会引发 System.InvalidOperationException。错误描述是荷兰语,翻译成类似:“查询使用不受支持的元素,例如对多个列表的引用或使用 EntityRef/EntitySet 投影完整实体”

如果我使用 EntitySet.Contains,我会得到同样的错误:

    private void fillCategorieDropdown(Intermediair.IntermediairDataContext idctx)
    {
        var contractenData = from c in idctx.Contracten
                             where c.LocatieS.Contains( 
                                 (  from l in idctx.Locaties 
                                    where l.Id == selectedLocatieId 
                                    select l
                                 ).First<Intermediair.LocatiesItem>() 
                             )
                             select c;
        var categorieenData = ( from ca in idctx.Categorieën
                                from co in contractenData
                                where ca.Contract.Contains(co) && ca.Meldingtype.Id == selectedMeldingtypeId
                                select ca
                              ).Distinct<Intermediair.CategorieënItem>();
        foreach (var categorie in categorieenData)
        {
            ctrl_Categorie.Items.Add(new ListItem(categorie.Titel, categorie.Id.ToString()));
        }
    }

我尝试了几种排列,但似乎找不到合适的排列。对于具有多查找字段的 linq-to-sharepoint 查询,我找不到任何好的示例,而且我对 linq 还不够熟练,所以我可能会犯一些市长错误。虽然我正在弄清楚这一点,但我真的很感激任何有用的想法。

[编辑:另一次尝试失败] 我尝试对所有步骤进行单独查询以检查中间结果。我还尝试了 Any-Contains 组合,以将类别的多查找合同与我从该位置获得的多个合同相匹配。

        var locatieItem = (from l in idctx.Locaties
                           where l.Id == selectedLocatieId
                           select l
                          ).First();
        var contractenData = from c in locatieItem.ContractenItem
                             select c;
        var categorieenData = from c in idctx.Categorieën
                              where c.Contract.Any(co => contractenData.Contains(co))
                              select c;
        var meldingtypeData = (from c in categorieenData
                               select c.Meldingtype
                              ).Distinct();
        foreach (var meldingtype in meldingtypeData)
        {
            ctrl_Meldingtype.Items.Add(new ListItem(meldingtype.Titel, meldingtype.Id.ToString()));
        }

locatieItem 和 contractenData 已按预期填充,但 categorieenData 再次生成相同的错误。[/编辑]

PS因为代码中的荷兰名字在英文中非常易读,所以我没有翻译名字。对困惑感到抱歉。

4

2 回答 2

0

SharePoint 2010 中的 linq 存在一些限制。也许这篇文章可以让您走上正轨: http: //www.chaholl.com/archive/2010/03/12/joins-in-linq-to-sharepoint-2010 .aspx

于 2011-02-21T14:58:51.907 回答
0

我已经解决了这个问题,有点。它确实带来了一些开销:从数据库中检索到的记录太多。但只有重复,所以希望缓存能解决大部分开销。

我现在使用的查询非常简单。

        var categorieenContractenData = from c in contractenData
                                        select c.CategorieënItem;

这并没有给我一组 CategorieItems,而是一组 CategorieItems,其中一些可以是重复的。然后我用双 foreach 循环遍历每个条目,并将这些条目放在三个数据结构中以便于检索。这意味着要填充三个下拉列表中的每一个,我只需要执行一个 linq-query。

我希望在本周末之前数据库中有一些真实的数据,所以我将测试它是否足够快。如果没有,我将不得不制作一个额外的列表(由事件接收者填写)。

完整代码:

    private void ensureLoadData(Intermediair.IntermediairDataContext idctx)
    {
        if (dataLoaded) return;

        meldingtypes = new SortedList<string, int?>();
        categorieen = new SortedList<int?,SortedList<string,int?>>();
        contracten = new SortedList<int?, SortedList<int?, SortedList<string, int?>>>();
        IQueryable<Intermediair.ContractenItem> contractenData = from c in
                                                                     (from l in idctx.Locaties
                                                                      where l.Id == selectedLocatieId
                                                                      select l
                                                                     ).SingleOrDefault().ContractenItem
                                                                 select c;
        var categorieenContractenData = from c in contractenData
                                        select c.CategorieënItem;
        foreach (EntitySet<Intermediair.CategorieënItem> categorieenPerContract in categorieenContractenData)
        {
            foreach (Intermediair.CategorieënItem categorie in categorieenPerContract)
            {
                if (!meldingtypes.ContainsKey(categorie.Meldingtype.Titel))
                {
                    meldingtypes.Add(categorie.Meldingtype.Titel, categorie.Meldingtype.Id);
                    categorieen.Add(categorie.Meldingtype.Id, new SortedList<string,int?>());
                    contracten.Add(categorie.Meldingtype.Id, new SortedList<int?, SortedList<string, int?>>());
                }
                if (!categorieen[categorie.Meldingtype.Id].ContainsKey(categorie.Titel))
                {
                    categorieen[categorie.Meldingtype.Id].Add(categorie.Titel, categorie.Id);
                    contracten[categorie.Meldingtype.Id].Add(categorie.Id, new SortedList<string,int?>());
                    foreach (Intermediair.ContractenItem contract in categorie.Contract)
                    {
                        contracten[categorie.Meldingtype.Id][categorie.Id].Add(contract.Titel, contract.Id);
                    }
                }
            }
        }
        dataLoaded = true;
    }
于 2011-03-01T11:19:46.543 回答