LINQ to Entities双表关联查询中IN子句的实现方法
问题背景
当前需要实现与T-SQL内连接查询逻辑完全等价的LINQ语句,已知信息如下:
- 可正常返回预期结果的原生SQL代码:
select * from [Website] as A inner join [OrderToWebsite] as B on A.WebsiteId = b.WebsiteId where B.OrderId in (25, 26, 29, 32)
- 待匹配的OrderId集合从Session中获取,取值代码:
var orderIDs = (List<int>)Session["OrderIds"];
- 目前未完成的LINQ片段缺失集合筛选逻辑,且select部分存在写法错误:
IEnumerable<Website> model = from A in _db.Websites join B in _db.OrderToWebsites on A.WebsiteId equals B.WebsiteId .........(不确定如何在此处加入orderIDs集合做匹配校验...) select B.OrderId.tolist();
- 涉及的两个视图模型定义:
- OrderToWebsiteViewModel
public class OrderToWebsiteViewModel { public int OrderToWebsiteId{ get; set; } public int OrderId { get; set; } public int WebsiteId { get; set; } public int CustomerAgrreementId { get; set; } public virtual int CustomerId { get; set; } public string CreatedBy { get; set; } public DateTime CreatedDate { get; set; } }- WebsiteViewModel
public class WebsiteViewModel { public int WebsiteId { get; set; } public string Name { get; set; } public string URL { get; set; } public DateTime? WebsiteAvailableBeginDate { get; set; } public DateTime? WebsiteAvailableEndDate { get; set; } public bool? ProposedWebsite { get; set; } public string CreatedBy { get; set; } public DateTime? CreatedDate { get; set; } public string Notes { get; set; } }
实现方法
LINQ中实现SQL的IN筛选逻辑直接使用集合的Contains()方法即可,EF/EF Core等主流ORM会自动将该方法翻译为对应的SQL IN语句,不会触发全表内存查询,性能与原生SQL一致。
修正后的完整LINQ代码(查询语法)如下:
// 取出待匹配的订单ID集合 var orderIDs = (List<int>)Session["OrderIds"]; IEnumerable<WebsiteViewModel> model = ( from site in _db.Websites join orderSiteRel in _db.OrderToWebsites on site.WebsiteId equals orderSiteRel.WebsiteId where orderIDs.Contains(orderSiteRel.OrderId) // 对应SQL的IN筛选逻辑 select site ).Distinct().ToList();
代码说明
- 内连接后直接追加where子句,通过
orderIDs.Contains(orderSiteRel.OrderId)即可实现OrderId集合匹配 - 追加
Distinct()是因为单个网站可能关联多个传入的订单ID,内连接后会产生重复的网站记录,去重后结果与业务预期的网站列表匹配 - 修正了原有代码中select部分的错误:原写法选择B.OrderId与声明的
IEnumerable<Website>返回类型不匹配,且ToList()是针对整个结果集的操作,需要放在查询最外层调用,不能写在单条记录的投影位置。
方法语法的等价写法如下:
var orderIDs = (List<int>)Session["OrderIds"]; var model = _db.Websites .Join( _db.OrderToWebsites, site => site.WebsiteId, rel => rel.WebsiteId, (site, rel) => new { site, rel } ) .Where(temp => orderIDs.Contains(temp.rel.OrderId)) .Select(temp => temp.site) .Distinct() .ToList();
内容的提问来源于stack exchange,提问作者Ron
相关产品推荐
相关产品推荐

