我从前一个人那里继承了这个项目,我现在正在将一些从字符串组装的SQL查询切换到LINQ to SQL,我被告知是生活在.NET值得一住。但是,我遇到了过滤多对多关系的问题。
该系统是项目管理内联网事务。主要对象/表格是 Project 。 Project 有许多 Markets ,它使用中间表 linkProjectMarkets 来链接它们。还有很多其他的事情正在发生,但如果我能理解这个问题,我可以照顾它,它们都很相似。
简而言之,我不能在我的生活中获取由一组复选框提供的市场ID列表,并将项目列表过滤到与提供ID的市场相关的项目列表。< / p>
架构的要点是:
项目:int id,...(一堆元数据)
linkProjectMarkets :int projectId,int marketId
市场:int id,字符串摘要
所有这些,任何许多,更多,都在dbml文件中定义并伴随生成的代码。为了便于项目和市场之间的访问,项目具有以下插件方法:
public partial class project
{
public EntitySet<market> markets
{
get
{
return (EntitySet<market>)from lpm in this._linkProjectMarkets
select lpm.market;
}
set
{
var set = (EntitySet<market>)from lpm in this._linkProjectMarkets
select lpm.market;
set.Assign(value);
}
}
}
这是我尝试用来过滤所有项目集的最新代码:
var projects =
from p in db.projects
select p;
//MarketFilterList is an IEnumerable of market ids created from the checked checkboxes.
if(MarketFilterList.Count() > 0){
foreach (int mid in MarketFilterList){
projects = projects.Where(p => p.markets.Select(m => m.id).Contains(mid));
/*
Causes "Member access 'Int32 id' of 'PMIS2.market' not legal on type
'System.Data.Linq.EntitySet`1[PMIS2.market]."
*/
}
}
还有许多其他过滤器可供应用,这就是为什么我要分步而不是一个LINQ语句。
我检查了设计师代码; linkProjectMarkets中的市场是公开的,而id在市场上是公开的。这是我第一次真正的C#/ .NET体验,所以也许我只是不理解错误信息。如果我给了太多,不够,或者没有正确的信息,请道歉。请帮忙!
P.S。我已经尝试过LINQ to Entities,我必须有一个非常好的理由再次尝试。
这是我尝试过的其他内容:
projects = projects.Where(
p => MarketFilterList.Intersect(from m in p.markets select m.id).Count() > 0
);
那个人告诉我:
除了Contains()运算符之外,本地序列不能用于查询运算符的LINQ to SQL实现。
这是基于JTew答案的解决方案。如果有人知道为什么项目无法直接进入市场,我很乐意听到它。
projects = projects.Where(p => (from lpm in db.linkProjectMarkets
where MarketFilterList.Contains(lpm.marketId)
select lpm.project).Contains(p));
答案 0 :(得分:1)
我会做以下事情:
var projMarkLink = from lpm in db.linkProjectMarkets select lpm;
建立IQueryable然后在后续行添加过滤器:
foreach (int mid in MarketFilterList){
projMarkLink = projMarkLink.Where(l => l.mid == mid);
}
然后选择您需要的结果:
return (from lpm in projMarkLink
from p in projMarkLink.Projects
select p).ToList();
您可以更进一步,删除循环,阅读this stackoverflow question。
return (from lpm in projMarkLink
from p in projMarkLink.Projects
where lpm.Contains(MarketFilterList)
select p).ToList();