我正在尝试获取一个列表中的项目,其中任何一个多重查找值都包含在另一个查询的结果中。
情况是这样的:我正在构建一个set部件,用户可以使用一组sharepoint (foundation 2010)列表为五个属性下拉列表生成报告(“融合”)。这些属性通过列表中的查找进行连接。每次更改下拉列表选择时,都会发生回发,并重新填充以下下拉列表。
问题是属性之间的连接并不是与下拉列表直接匹配的。这是因为选择下拉输入是为了直观地输入报告,而数据模型是为了方便和直观地输入系统数据而设计的,而不是为了高效和容易的编程而设计的。
数据模型的相关部分:
-Locaties (位置)是一个列表
-Contracten (合同)是一个列表,每个合同都有一个或多个位置(多查找)
-Urgentie (紧急)是一个列表,每个紧急事件都有一个契约(查找)
-Meldingtypes (reporttype)是一个列表
类别( -Categorieën )是一个列表,每个类别有一个meldingtype (查找),每个类别有一个或多个契约(多个查找)
报告输入如下:
用户首先选择位置
用户选择Meldingtype秒
用户选择第三个类别
用户选择第四个合同
最后,用户选择Urgentie
当然,每次下拉列表都应该只填充有效的选项。因此,当选择一个位置时,下拉列表中显示的唯一meldingtypes应该是那些具有所选location...yeah的合同的类别;)
我在创建查询来填充dropdowns时遇到了问题。我已经尝试了几种方法,包括多个查询,使用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组合,将categorie的多个查找合同与我从该位置获得的多个合同进行匹配。
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再次生成相同的错误。/Edit
另外,因为代码中的荷兰语名字在英文中非常易读,所以我没有翻译这些名字。很抱歉给你造成了混乱。
发布于 2011-03-01 19:19:47
我已经解决了这个问题。它确实带来了一些开销:从数据库中检索了太多的记录。但只有重复,所以希望缓存能解决大部分开销。
我现在使用的查询非常简单。
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-02-21 22:58:52
在SharePoint 2010中,linq有一些限制。也许这篇文章可以帮你找到正确的方向:http://www.chaholl.com/archive/2010/03/12/joins-in-linq-to-sharepoint-2010.aspx
https://stackoverflow.com/questions/5066194
复制相似问题