将 SQL 转换为带有 null 的 Linq 左连接
Posted
技术标签:
【中文标题】将 SQL 转换为带有 null 的 Linq 左连接【英文标题】:Convert SQL to Linq left join with null 【发布时间】:2012-02-07 04:35:49 【问题描述】:我怎样才能正确地将这个 SQL 转换为 linq
select t1.ProgramID
from Program t1 LEFT JOIN ProgramLocation t2 ON t1.ProgramID = t2.ProgramID
where t2.ProgramID IS NULL
我试过了,还是不行
var progy = (
from u in db.ProgramLocations join b in db.Programs
on u.ProgramID equals b.ProgramID into yG
from y1 in yG.DefaultIfEmpty()
where u.ProgramID == null
where u.ProgramID == null
select u.ProgramID
).ToList();
谢谢
【问题讨论】:
试过linqpad.net? 这会将 SQL 转换为 LINQ 【参考方案1】:你想使用.DefaultIfEmpty
,就像this question一样。
var query = from p in Programs
join pl in ProgramLocations
on p.ProgramID equals pl.ProgramID into pp
from pl in pp.DefaultIfEmpty()
where pl == null
select p;
这是一个包含一些模拟数据对象的完整工作示例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LinqTest
class LinqProgram
public class Program
public int ProgramID get; set;
public string ProgramName get; set;
public class ProgramLocation
public int ProgramLocationID get; set;
public int ProgramID get; set;
public string ProgramLocationName get; set;
public static List<Program> Programs = new List<Program>();
public static List<ProgramLocation> ProgramLocations = new List<ProgramLocation>();
static void Main(string[] args)
FillTestData();
var query = from p in Programs
join pl in ProgramLocations
on p.ProgramID equals pl.ProgramID into pp
from pl in pp.DefaultIfEmpty()
where pl == null
select p;
foreach (var r in query)
Console.WriteLine("0: 1", r.ProgramID, r.ProgramName);
Console.ReadLine();
private static void FillTestData()
var p = new Program()
ProgramID = Programs.Count + 1,
ProgramName = "Scary Lesson"
;
var pl = new ProgramLocation()
ProgramLocationID = ProgramLocations.Count + 1,
ProgramID = p.ProgramID,
ProgramLocationName = "Haunted House"
;
Programs.Add(p);
ProgramLocations.Add(pl);
p = new Program()
ProgramID = Programs.Count + 1,
ProgramName = "Terrifying Teachings"
;
pl = new ProgramLocation()
ProgramLocationID = ProgramLocations.Count + 1,
ProgramID = p.ProgramID,
ProgramLocationName = "Mystical Mansion"
;
Programs.Add(p);
ProgramLocations.Add(pl);
p = new Program()
ProgramID = Programs.Count + 1,
ProgramName = "Unassociated Program"
;
Programs.Add(p);
【讨论】:
【参考方案2】:试试这个
var progy = (
from u in db.ProgramLocations join b in db.Programs
on u.ProgramID equals b.ProgramID into yG
from y1 in yG.DefaultIfEmpty()
where y1 == null
select u.ProgramID
).ToList();
您可以查看this post on MSDN。
希望这对你有用。
【讨论】:
【参考方案3】:你能用 except 代替吗?
var progy = (
from u in db.ProgramLocations
select u.ProgramID
).Except(from b in db.Programs select b.ProgramID);
【讨论】:
这只有在 ProgramID 是您需要检索的唯一值时才有效。【参考方案4】:SELECT pfa.PetID, pt.PetTypeDesc, pfa.petname, pf.PetOwner, pf.remarks, pat.AdoptedBy
FROM dbo.PetForAdoption pfa
JOIN dbo.PetAdoptionTran pat
ON pfa.PetID = pat.PetID
JOIN dbo.PetTypes pt
ON pfa.PetTypeID = pt.PetTypeID
JOIN dbo.PetProfile pf
ON pfa.PetID = pf.PetID
ORDER BY pt.PetTypeDesc
【讨论】:
虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高答案的长期价值。请阅读此how-to-answer 以提供高质量的答案。【参考方案5】:我现在遇到了这个问题,整洁的 SQL 是必须的,并且以非常优化的方式运行。
林克:
var recs=from programs in db.Programs
from locations in db.ProgramLocations.where(x=> x.ProgramID == programs.ProgramID).DefaultIfEmpty()
where locations.ProgramID == null //Compiler creates a warning because int will never be null, but it works and creates outer left join
select programs.ProgramID;
生成的 SQL:
SELECT
"Extent1"."ProgramID" AS "ProgramID"
FROM "DBO"."Program" "Extent1"
LEFT OUTER JOIN "DBO"."ProgramLocation" "Extent2" ON "Extent2"."ProgramID" = "Extent1"."ProgramID"
WHERE ("Extent2"."ProgramID" IS NULL)
如果您有多个连接条件,这也适用并且也适用于多个左连接
ps。我将 EF 与 Oracle 一起使用,因此不确定这在 E 的 SQLServer 提供程序上是否会略有不同
【讨论】:
以上是关于将 SQL 转换为带有 null 的 Linq 左连接的主要内容,如果未能解决你的问题,请参考以下文章
C# 将带有 Case 语句的 SQL 查询转换为 LINQ
如何将带有 LEFT JOIN 的 SQL 转换为 EF CORE 3 LINQ