如何通过导航属性链接2个实体时表示LEFT JOIN

时间:2018-03-28 23:00:44

标签: c# entity-framework linq

假设我有这两个实体

if(r.next())
{
   System.out.println("User Name Does Exist");
}
else
{
   System.out.println("User Does Not Exist");
}

我使用此代码选择产品列表。它们中的每一个都将与给定产品显示位置的图像相关联。

public class Product
{
   //..
   public ICollection<Photo> Photos { get; set; }
          = new List<Photo>();
}

public class Photo
{
  //..
  public PageLocation PageLocation { get; set; }
  public int ProductId { get; set; }
  public Product Product { get; set; }
}

问题是,当产品没有该位置的图像时,则不会选择该产品。

我在左连接中看到的

Every examples显示了如何使用2个来源。在我的情况下,我不需要2个来源,因为我在Product和Image之间有一个导航属性。

有没有办法在不使用2个数据源的情况下完成左连接?像这样的东西

var productList = GetAll().Include(p => p.PhotoImages)
        .Where(p =>
               p.PhotoImages.Any(
                     i => i.PageLocation == PageLocation.Home_Slider));

感谢您的帮助

2 个答案:

答案 0 :(得分:0)

  

有没有办法在不使用2个数据源的情况下完成左连接?

我认为没有。在您的SQL查询中,您将加入一个新集,而不是与您的产品相关的照片。

我相信你能做的最好的事情就是这样:

var q = from prod in ctx.Products.Include(p => p.Photos) 
        join img in (
            from ph in ctx.Photos where ph.PageLocation == 1 select new { ph.ProductId, PageLocation = (int?)ph.PageLocation }
        ) on prod.Id equals img.ProductId into pjoin
        from pj in pjoin.DefaultIfEmpty()
        select new { prod, photo = pj, pj.PageLocation };

foreach (var p in q)
{
     Console.WriteLine($"{p.prod.Id} - {p.photo} - {p.PageLocation}");
}

编辑:此查询中只有一个连接,从生成的SQL中可以看出:

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[Name] AS [Name], 
[Extent2].[PageLocation] AS [PageLocation], 
[Extent2].[ProductId] AS [ProductId]
FROM  [dbo].[Product] AS [Extent1]
LEFT OUTER JOIN [dbo].[Photo] AS [Extent2] ON (1 = [Extent2].[PageLocation]) AND ([Extent1].[Id] = [Extent2].[ProductId])

答案 1 :(得分:0)

好吧,如果使用导航属性,EF会生成一个inner join的SQL语句。

  

导航属性如何工作

     

当我们在代码中应用导航属性时,这意味着我们要求EF自动执行两个表之间的连接。

来源: Navigation Property With Code First (Navigation Property In EF)

因此,您可以使用MS docs - Perform left outer joins上已经找到的示例 - 来实现您的查询。您的SQL示例也有两个来源。第一个Products表和第二个PhotoImages表或我误解了你的意思。

您的查询方法可以是:

var products = (
    from p in _context.Products
    join pi in _context.PhotoImages on p.Id equals pi.ProductId
    into productsWithImages

    from pwi in productsWithImages.Where(pwi => pwi.PageLocation == 1).DefaultIfEmpty()
    select new ExtendedProduct
    {
        p.Id,
        p.Name,
        photoId = (int?)pwi.Id,
        pwi.PageLocation,
        pwi.Url
    }
)
相关问题