[SOLVED] Entity Framework Left Join The error I got while using

Issue

I was writing a query that I want to get what’s in one of my lists and what’s in the other, and I encountered this error.

enter image description here

My code is here, when I type join instead of left join, it works fine, but the value I want is not coming, please help 😀

 var orgRolOlanDuyurular = _context.DuyuruOrgRol.Include(x=>x.Duyuru).ThenInclude(l => l.KL_DuyuruTur).Where(l => l.Duyuru.AktifMi);
 var tumDuyurular = _context.Duyuru.Include(l => l.KL_DuyuruTur).Where(l => l.AktifMi);
 var c = tumDuyurular.LeftJoin(orgRolOlanDuyurular,
                                tmDuyurular => tmDuyurular.Id,
                                orgOlanDuyurular => orgOlanDuyurular.DuyuruId,
                                (tmDuyurular, orgOlanDuyurular) => new DuyuruPaging{Id = tmDuyurular.Id, BaslangicTarihi = tmDuyurular.BaslangicTarihi, BitisTarihi = tmDuyurular.BitisTarihi, DuyuruTurAd = tmDuyurular.KL_DuyuruTur.Ad, Konu = tmDuyurular.Konu });

Solution

A left outer join is a join in which each element of the first collection is returned, regardless of whether it has any correlated elements in the second collection. You can use LINQ to perform a left outer join by calling the DefaultIfEmpty method on the results of a group join.

There is no such syntax exactly the same as T-SQL to use Left or Right joins. However, there is a similar approach that you can leverage.

Assuming that you have two Entities. SalesOrderDetail and Product:

public partial class SalesOrderDetail
{
    public int SalesOrderID { get; set; }
    public short OrderQty { get; set; }
    public int ProductID { get; set; }
    public decimal UnitPrice { get; set; }
    public decimal LineTotal { get; set; }
    public override string ToString()
    {
        StringBuilder sb = new StringBuilder(1024);

        sb.AppendLine($"Order ID: {SalesOrderID}");
        sb.Append($"   Product ID: {ProductID}");
        sb.AppendLine($"   Qty: {OrderQty}");
        sb.Append($"   Unit Price: {UnitPrice:c}");
        sb.AppendLine($"   Total: {LineTotal:c}");

        return sb.ToString();
    }
}

And Product as per below:

public partial class Product
{
    public int ProductID { get; set; }
    public string Name { get; set; }
    public string Color { get; set; }
    public decimal StandardCost { get; set; }
    public decimal ListPrice { get; set; }
    public string Size { get; set; }

    // Calculated Properties
    public int? NameLength { get; set; }
    public decimal? TotalSales { get; set; }
    public override string ToString()
    {
        StringBuilder sb = new StringBuilder(1024);

        sb.Append(Name);
        sb.AppendLine($"  ID: {ProductID}");
        sb.Append($"   Color: {Color}");
        sb.AppendLine($"   Size: {(Size ?? "n/a")}");
        sb.Append($"   Cost: {StandardCost:c}");
        sb.Append($"   Price: {ListPrice:c}");
        if (NameLength.HasValue)
        {
            sb.AppendLine($"   Name Length: {NameLength}");
        }
        if (TotalSales.HasValue)
        {
            sb.AppendLine($"   Total Sales: {TotalSales:c}");
        }
        return sb.ToString();
    }
}

Now Perform a left join between Products and Sales using DefaultIfEmpty() and SelectMany() as per below:

var query = (from prod in Products
         join sale in Sales
         on prod.ProductID equals sale.ProductID
           into sales
         from sale in sales.DefaultIfEmpty()
         select new
         {
             prod.ProductID,
             prod.Name,
             prod.Color,
             prod.StandardCost,
             prod.ListPrice,
             prod.Size,
             sale?.SalesOrderID,
             sale?.OrderQty,
             sale?.UnitPrice,
             sale?.LineTotal
         }).OrderBy(ps => ps.Name);

If you wish to use method syntax, you can achieve the same result as per below code:

var query = Products.SelectMany(
          sale =>
          Sales.Where(s => sale.ProductID == s.ProductID).DefaultIfEmpty(),
          (prod, sale) => new
          {
              prod.ProductID,
              prod.Name,
              prod.Color,
              prod.StandardCost,
              prod.ListPrice,
              prod.Size,
              sale?.SalesOrderID,
              sale?.OrderQty,
              sale?.UnitPrice,
              sale?.LineTotal
          }).OrderBy(ps => ps.Name);

Now you can use a simple foreach loop as per below:

foreach (var item in query)
{
    count++;
    sb.AppendLine($"Product Name: {item.Name} ({item.ProductID})");
    sb.AppendLine($"  Order ID: {item.SalesOrderID}");
    sb.AppendLine($"  Size: {item.Size}");
    sb.AppendLine($"  Order Qty: {item.OrderQty}");
    sb.AppendLine($"  Total: {item.LineTotal:c}");
}

For more information, you can visit https://docs.microsoft.com/en-us/dotnet/csharp/linq/perform-left-outer-joins

Answered By – Mohi

Answer Checked By – Jay B. (BugsFixing Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *