【问题标题】:LINQ To SQL: Filtering a query across many tablesLINQ To SQL:过滤跨多个表的查询
【发布时间】:2010-02-11 19:37:31
【问题描述】:

我从前一个人那里继承了这个项目,我目前正在将一些从字符串组装的 SQL 查询转换为 LINQ to SQL,我被告知这是生活的原因.NET 值得生活。但是,我在过滤多对多关系时遇到了问题。

该系统是一个项目管理内部网事务。注意的主要对象/表是项目Project 有许多 Markets,它们使用中间表 linkProjectMarkets 来链接它们。还有很多其他的事情发生了,但如果我能理解这个问题,我可以解决这个问题,这都是相似的。

简而言之,我无法终生获取由一组复选框提供的市场 ID 列表,并将项目列表过滤到与提供 ID 的市场相关的项目。

架构的要点是:

项目:int id,...(一堆元数据)
linkProjectMarkets:int projectId,int marketId
Market strong>:int id,字符串摘要

所有这些,还有很多很多,都在一个 dbml 文件和随附的生成代码中定义。为了方便projectmarket之间的访问,project有如下插件方法:

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 中的 market 是公开的,而市场中的 id 是公开的。这是我第一次真正的 C#/.NET 体验,所以也许我只是不理解错误消息。如果我提供了太多、不够或不正确的信息,我深表歉意。请帮忙!

附:我已经尝试过 LINQ to Entities,我必须有充分的理由再试一次。

编辑

这是我尝试过的其他方法:

projects = projects.Where(
    p => MarketFilterList.Intersect(from m in p.markets select m.id).Count() > 0
);

那个人告诉我的:

本地序列不能在查询运算符的 LINQ to SQL 实现中使用,但 Contains() 运算符除外。

再次编辑

这是基于 JTew 回答的解决方案。如果有人有项目无法直接进入市场的真正原因,我很想听听。

projects = projects.Where(p => (from lpm in db.linkProjectMarkets
                                where MarketFilterList.Contains(lpm.marketId)
                                select lpm.project).Contains(p));

【问题讨论】:

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


    【解决方案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();
    

    【讨论】:

    • 谢谢!直接使用 linkProjectMarkets 表就可以了。我不太高兴打破项目市场抽象,但只要它有效。
    • 在我的例子中,抽象是通过这个代码的存储库模式,我只会把它放在数据层中。查询从 linkProjectMarkets 开始,因为它在执行时生成最佳 sql(至少使用 EF)。如果您对答案感到满意,请单击答案旁边投票面板下方的勾号。谢谢,很高兴它成功了。
    • 当然,我只是在等着看是否有人会做得更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 2015-05-22
    • 1970-01-01
    相关资源
    最近更新 更多