LINQ to SQL:跨多个表过滤查询

时间:2010-02-11 19:37:31

标签: c# .net linq-to-sql

我从前一个人那里继承了这个项目,我现在正在将一些从字符串组装的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));

1 个答案:

答案 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();