如何用LINQ to SQL实现带过滤后子列表的父对象查询
嘿,我来帮你把那条SQL转换成LINQ to SQL查询,同时实现你要的「包含已过滤子列表的对象集合」的需求~
首先先明确原SQL的逻辑:关联Pages、Translations、Texts三张表,过滤出LanguageId=1的文本,同时保证Translation的NeutralText和Page的TitleNeutralTextId匹配。
方法一:基于查询语法(和原SQL结构最接近,易读性高)
假设你的DbContext里有Translations和Texts两个DbSet,且this.Queryable()返回的是IQueryable<Page>,可以这么写:
var query = from p in this.Queryable() join translation in dbContext.Translations on p.TranslationId equals translation.Id join text in dbContext.Texts on translation.Id equals text.TranslationId where text.LanguageId == 1 && translation.NeutralText == p.TitleNeutralTextId select new { Page = p, MatchingText = text };
不过如果你的需求是每个Page对象附带符合条件的子文本列表(而不是一对一的平级结果),那需要用分组来实现:
方法二:分组获取带过滤子列表的Page集合
如果想返回每个Page对应的所有符合条件的Texts子集合,可以用分组查询:
// 先定义一个类来封装结果(如果不需要强类型也可以用匿名类) public class PageWithFilteredTexts { public Page Page { get; set; } public IEnumerable<Text> FilteredTexts { get; set; } } // 构建查询 var query = this.Queryable() // 第一步关联Page和Translation .Join(dbContext.Translations, page => page.TranslationId, translation => translation.Id, (page, translation) => new { page, translation }) // 过滤Translation和Page的NeutralText匹配条件 .Where(joinResult => joinResult.translation.NeutralText == joinResult.page.TitleNeutralTextId) // 第二步关联Text .Join(dbContext.Texts, joinResult => joinResult.translation.Id, text => text.TranslationId, (joinResult, text) => new { joinResult.page, text }) // 过滤LanguageId=1的文本 .Where(finalResult => finalResult.text.LanguageId == 1) // 按Page分组,把同一个Page的所有符合条件的Texts归为一组 .GroupBy(finalResult => finalResult.page) // 投影成我们需要的带子列表的对象 .Select(group => new PageWithFilteredTexts { Page = group.Key, FilteredTexts = group.Select(item => item.text) });
方法三:利用导航属性简化(如果实体类配置了导航关系)
如果你的实体类已经配置了导航属性(比如Page有Translation属性,Translation有Texts集合属性),那代码会更简洁:
var query = this.Queryable() // 先过滤出符合条件的Page .Where(page => page.Translation.NeutralText == page.TitleNeutralTextId && page.Translation.Texts.Any(text => text.LanguageId == 1)) // 投影时只取符合条件的Texts子列表 .Select(page => new PageWithFilteredTexts { Page = page, FilteredTexts = page.Translation.Texts.Where(text => text.LanguageId == 1) });
这种写法更直观,LINQ to SQL会自动帮你生成对应的关联查询,和你给出的SQL逻辑一致。
内容的提问来源于stack exchange,提问作者David Létourneau
相关产品推荐
相关产品推荐

