EF Core中如何使用LEFT JOIN
我们知道使用EF Core的Join函数可以实现SQL中的INNER JOIN,那么怎么实现LEFT JOIN呢?
答案就在GroupJoin、SelectMany和DefaultIfEmpty三个Linq函数的组合使用上。
下面我们举个例子,建立一个.NET Core控制台项目,来演示使用EF Core将Person表来LEFT JOIN Products表。
Person表在EF Core中的实体类,如下:
public partial class Person { public int Id { get; set; } public string Name { get; set; } public int? Age { get; set; } public DateTime? CreateTime { get; set; } public string Flag { get; set; } public string VarCharDescription { get; set; } }
Products表在EF Core中的实体类,如下:
public partial class Products { public int Id { get; set; } public string Product { get; set; } }
然后Person表和Products表,在SQL Server数据库中的数据如下所示:
最后我们要结合GroupJoin、SelectMany和DefaultIfEmpty三个Linq函数,来在EF Core上实现Person LEFT JOIN Products的SQL语句,如下所示:
class Program { static void Main(string[] args) { using (TestDBContext dbContext = new TestDBContext()) { //Person LEFT JOIN Products var joinResults = dbContext .Person .GroupJoin(dbContext.Products, person => person.Id, product => product.Id, (person, products) => new { Person = person, Products = products }) .SelectMany(combination => combination.Products.DefaultIfEmpty(), (person, products) => new { PersonId = person.Person.Id, PersonName = person.Person.Name, ProductsId = products.Id, ProductsName = products.Product }).ToList(); foreach (var joinResult in joinResults) { Console.WriteLine("PersonId={0}, PersonName={1}, ProductsId={2}, ProductsName={3}", joinResult.PersonId.ToString(), joinResult.PersonName == null ? "Null" : joinResult.PersonName, joinResult.ProductsId.ToString(), joinResult.ProductsName == null ? "Null" : joinResult.ProductsName); } } Console.WriteLine("Press any key to end..."); Console.ReadKey(); } }
我们可以通过EF Core的后台日志,看到EF Core生成的SQL语句如下所示:
SELECT [p].[ID] AS [PersonId], [p].[Name] AS [PersonName], [p0].[id] AS [ProductsId], [p0].[product] AS [ProductsName] FROM [Person] AS [p] LEFT JOIN [products] AS [p0] ON [p].[ID] = [p0].[id]
该语句在数据库中,执行结果如下:
然后我们可以看到我们的.NET Core程序,输出的结果如下:
可以看到,由于EF Core中实体类Products的Id属性为int类型,不能为null,所以EF Core将Products表中为null的行输出为了ProductsId=0,而由于实体类Products的Product属性为string类型,可以为null,所以EF Core将Products表中为null的行输出为了ProductsName=Null。
所以可以看到如果要在EF Core中实现LEFT JOIN还是有点麻烦的,所以我建议如果在开发过程中我们要写一些很复杂的LEFT JOIN、RIGHT JOIN、FULL JOIN等SQL语句,可以将这些SQL语句写成数据库中的视图或存储过程等数据库对象,然后使用EF Core将数据库中的视图或存储过程等映射为实体类,这样比在EF Core中去构造复杂的SQL语句要方便很多。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
2017-02-17 IIS中ASP.NET虚拟目录不继承主站点web.config设置的办法(转载)
2010-02-17 Visual Studio 2008 远程调试