using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
// Customer collection
IList<Customer> CustomertList = new List<Customer>() {
new Customer() { CustomerID = 1, CustomerName = "John", OrderID = 04 } ,
new Customer() { CustomerID = 2, CustomerName = "Moin", OrderID = 07 } ,
};
// Transaction collection
IList<Transaction> TransactionList = new List<Transaction>() {
new Transaction() { TransactionID = 1, OrderID = 04, Purchased = "TV",StoreName ="Amazon"} ,
new Transaction() { TransactionID = 2, OrderID = 07, Purchased = "Laptop",StoreName ="Ebay"} ,
new Transaction() { TransactionID = 3, OrderID = 07, Purchased = "Mobile",StoreName ="Ebay"} ,
};
// LINQ Query
var result =(from Cus in CustomertList
join TRan in TransactionList on Cus.OrderID equals TRan.OrderID
select new
{
CustomerName =Cus.CustomerName,
OrderID = Cus.OrderID,
StoreName =TRan.StoreName
}).ToList();
foreach(var Cus in result){
Console.WriteLine( "Name - {0} , Order ID - {1} , StoreName - {2}",Cus.CustomerName , Cus.OrderID,Cus.StoreName);
}
}
}
public class Customer
{
public int CustomerID { get; set; }
public string CustomerName { get; set; }
public int OrderID { get; set; }
}
public class Transaction
{
public int TransactionID { get; set; }
public int OrderID { get; set; }
public string Purchased { get; set; }
public string StoreName { get; set; }
}
Result :
Name - John, Order ID - 4, StoreName - Amazon
Name - Moin, Order ID - 7, StoreName - Ebay
Name - Moin, Order ID - 7, StoreName - Ebay
From the above code i am getting the above result,I need to show what are all order and Customer name and Store where they purchase, but i am getting duplicate values, i put the normal join query but i need below Expected result.
Expected Result :
Name - John, Order ID - 4, StoreName - Amazon
Name - Moin, Order ID - 7, StoreName - Ebay .
just try this
.....
select new
{
CustomerName = Cus.CustomerName,
OrderID = Cus.OrderID,
StoreName = TRan.StoreName
}).Distinct().ToList();
It's duplicating because your key is duplicated... If you try what Serge said it'll works fine.
// LINQ Query
var result =(from Cus in CustomertList
join TRan in TransactionList on Cus.OrderID equals TRan.OrderID
select new
{
CustomerName =Cus.CustomerName,
OrderID = Cus.OrderID,
StoreName =TRan.StoreName
}).Distinct().ToList();
OR you can group by CustomerName, OrderID and StoreName in TransactionList before your result query. Using GroupBy you won't need to use Distinct()
Related
Sorry for my bad English.
Here is my SQL Design.
I have 3 table in Sqlsever. Each table has 4 column with same name, same datatype.
And i want to get data from 4 column "Id, Name, Quantity, IdCategory" from 3 table into 1 list object same as returning value in this code below:
public async Task<IEnumerable<Shirt>> LoadAllShirt()
{
return await _dbContext.Shirt.ToListAsync();
}
I use .NET Core 6 Mvc - code first. Thanks for your help.
I have 3 table in Sqlsever. Each table has 4 column with same name,
same datatype. And I want to get data from 4 column "Id, Name,
Quantity, IdCategory" from 3 table into 1 list, I use .NET Core 6 Mvc - code first.
Well, lot of way around to handle this kind of scenario. Most easy and convenient way I would prefer to use View model or using Linq query.
Lets assume you have below Models:
Models:
public class Bags
{
public int Id { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
public string Category { get; set; }
}
public class Shirts
{
public int Id { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
public string Category { get; set; }
}
public class Shoes
{
public int Id { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
public string Category { get; set; }
}
Seeds In Models:
List<Bags> listBags = new List<Bags>();
listBags.Add(new Bags() { Id = 101, Name = "Bag A", Quantity =10, Category = "Cat-A"});
listBags.Add(new Bags() { Id = 102, Name = "Bag B", Quantity =15, Category = "Cat-A"});
listBags.Add(new Bags() { Id = 103, Name = "Bag C", Quantity =20, Category = "Cat-A"});
List<Shirts> listShirts = new List<Shirts>();
listShirts.Add(new Shirts() { Id = 101, Name = "Shirt A", Quantity = 10, Category = "Cat-B" });
listShirts.Add(new Shirts() { Id = 102, Name = "Shirt B", Quantity = 15, Category = "Cat-B" });
listShirts.Add(new Shirts() { Id = 103, Name = "Shirt C", Quantity = 20, Category = "Cat-B" });
List<Shoes> listShoes = new List<Shoes>();
listShoes.Add(new Shoes() { Id = 101, Name = "Shirt A", Quantity = 10, Category = "Cat-S" });
listShoes.Add(new Shoes() { Id = 102, Name = "Shirt B", Quantity = 15, Category = "Cat-S" });
listShoes.Add(new Shoes() { Id = 103, Name = "Shirt C", Quantity = 20, Category = "Cat-S" });
Way: 1 using ViewModel:
public class AllViewModel
{
public List<Bags> Bags { get; set; }
public List<Shirts> Shirts { get; set; }
public List<Shoes> Shoes { get; set; }
}
Query Using ViewModel:
var allTableUsingViewModel = new AllViewModel();
allTableUsingViewModel.Bags = listBags;
allTableUsingViewModel.Shirts = listShirts;
allTableUsingViewModel.Shoes = listShoes;
Output Using ViewModel:
Way: 2 using Linq Annonymous Type:
Query Using Linq Annonymous Type:
var AllTableListUsingLinq = from a in listBags
join b in listShirts on a.Id equals b.Id
join c in listShoes on b.Id equals c.Id
select new
{
FromBagsID = a.Id,
FromBagsName = a.Name,
FromBagsQuantity = a.Quantity,
FromBagsCategory = a.Category,
FromShirtsID = b.Id,
FromShirtsName = b.Name,
FromShirtsQuantity = b.Quantity,
FromShirtsCategory = b.Category,
FromShoesID = c.Id,
FromShoesName = c.Name,
FromShoesQuantity = c.Quantity,
FromShoesCategory = c.Category
};
Output Using Linq Annonymous Type:
Full Controller:
[HttpGet("GetFrom3Tables")]
public IActionResult GetFrom3Tables()
{
List<Bags> listBags = new List<Bags>();
listBags.Add(new Bags() { Id = 101, Name = "Bag A", Quantity =10, Category = "Cat-A"});
listBags.Add(new Bags() { Id = 102, Name = "Bag B", Quantity =15, Category = "Cat-A"});
listBags.Add(new Bags() { Id = 103, Name = "Bag C", Quantity =20, Category = "Cat-A"});
List<Shirts> listShirts = new List<Shirts>();
listShirts.Add(new Shirts() { Id = 101, Name = "Shirt A", Quantity = 10, Category = "Cat-B" });
listShirts.Add(new Shirts() { Id = 102, Name = "Shirt B", Quantity = 15, Category = "Cat-B" });
listShirts.Add(new Shirts() { Id = 103, Name = "Shirt C", Quantity = 20, Category = "Cat-B" });
List<Shoes> listShoes = new List<Shoes>();
listShoes.Add(new Shoes() { Id = 101, Name = "Shirt A", Quantity = 10, Category = "Cat-S" });
listShoes.Add(new Shoes() { Id = 102, Name = "Shirt B", Quantity = 15, Category = "Cat-S" });
listShoes.Add(new Shoes() { Id = 103, Name = "Shirt C", Quantity = 20, Category = "Cat-S" });
//Way: 1 Linq Query
var AllTableListUsingLinq = from a in listBags
join b in listShirts on a.Id equals b.Id
join c in listShoes on b.Id equals c.Id
select new
{
FromBagsID = a.Id,
FromBagsName = a.Name,
FromBagsQuantity = a.Quantity,
FromBagsCategory = a.Category,
FromShirtsID = b.Id,
FromShirtsName = b.Name,
FromShirtsQuantity = b.Quantity,
FromShirtsCategory = b.Category,
FromShoesID = c.Id,
FromShoesName = c.Name,
FromShoesQuantity = c.Quantity,
FromShoesCategory = c.Category
};
//Way: 2 : ViewModel
var allTableUsingViewModel = new AllViewModel();
allTableUsingViewModel.Bags = listBags;
allTableUsingViewModel.Shirts = listShirts;
allTableUsingViewModel.Shoes = listShoes;
return Ok(AllTableListUsingLinq);
}
Note: If you need more information you could check our official document for View Model and Linq Projction here
The following sample query will list your 3 types of data into a single result set.
var allResults = resultSet1.Concat(resultSet2);
For the return type create a class which will be the parent class for all your products (Bag,Shirt,Shoes) Which will help you to return data in a single Generic data.
If you use any non-generic list to send the data like hashtable or Arraylist then then there will be no issue.
In my way I will suggest to use generic data list as it will help you fetch data in better time complexity.
In this case you may need to define additional indirect base class with these 4 parameters. Than you can create Collection of this base class, and concatinate all 3 tables into.
public class BaseEntity
{
public string Name {get;set;}
}
public class Shoes : BaseEntity
{
}
...
public IEnumerable<BaseEntity> GetAllTables()
{
var shirts = await _dbContext.Shirt.ToListAsync();
var shoes = await _dbContext.Shoes.ToListAsync();
var bags = await _dbContext.Bags.ToListAsync();
return shirts.Concat(shoes).Concat(bags);
}
Similar example but witout casting to base class is shown in Enumerable.Concat documentation: https://learn.microsoft.com/pl-pl/dotnet/api/system.linq.enumerable.concat?view=net-7.0
I have two tables, Employees and Transactions.
First table: dbo.Employees
Second table: dbo.Transactions
I need to convert the below query to a lambda expression (Linq):
SELECT Employees.EmployeeId, Trans.LastTrans
FROM dbo.Employees
INNER JOIN
(SELECT EmployeeId, MAX(TrasactionDate) LastTrans
FROM dbo.Transactions
GROUP BY EmployeeId) Trans ON Trans.EmployeeId = Employees.EmployeeId
I want the result employeeId and LastTrans as shown below:
See following. The query does not need two Select in linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Context db = new Context()
{
Employees = new List<Employees>() {
new Employees() { EmployeeId = 1, Name = "Hossam"},
new Employees() { EmployeeId = 2, Name = "Peter"},
new Employees() { EmployeeId = 3, Name = "George"}
},
Transactions = new List<Transactions>() {
new Transactions() { TranactionId = 1, amount = 200, TransactionDate = DateTime.Parse("2020-01-02"), EmployeeId = 1},
new Transactions() { TranactionId = 2, amount = 300, TransactionDate = DateTime.Parse("2020-02-02"), EmployeeId = 1},
new Transactions() { TranactionId = 3, amount = 1000, TransactionDate = DateTime.Parse("2020-02-25"), EmployeeId = 1},
new Transactions() { TranactionId = 4, amount = 5000, TransactionDate = DateTime.Parse("2020-04-01"), EmployeeId = 2},
new Transactions() { TranactionId = 5, amount = 7000, TransactionDate = DateTime.Parse("2020-07-16"), EmployeeId = 2},
new Transactions() { TranactionId = 6, amount = 8000, TransactionDate = DateTime.Parse("2020-08-06"), EmployeeId = 3},
new Transactions() { TranactionId = 6, amount = 600, TransactionDate = DateTime.Parse("2020-09-04"), EmployeeId = 3}
}
};
var results = (from trans in db.Transactions
join emp in db.Employees on trans.EmployeeId equals emp.EmployeeId
select new { EmployeeId = trans.EmployeeId, LastTrans = trans.TransactionDate }
).GroupBy(x => x.EmployeeId)
.Select(x => x.OrderByDescending(y => y.LastTrans))
.Select(x => x.First())
.OrderBy(x => x.EmployeeId)
.ToList();
}
}
public class Context
{
public List<Employees> Employees { get; set; }
public List<Transactions> Transactions { get; set; }
}
public class Employees
{
public int EmployeeId { get; set; }
public string Name { get; set; }
}
public class Transactions
{
public int TranactionId { get; set; }
public decimal amount { get; set; }
public DateTime TransactionDate { get; set; }
public int EmployeeId { get; set; }
}
}
This query is enough to get your result and you do not need additional join to Employees
var grouped =
from trans in db.Transactions
group trans by trans.EmployeeId into g
select new
{
EmployeeId = g.Key,
LastTrans = g.Max(x => x.TrasactionDate)
};
I have retrieve a list of employees. my employee class columns(employeeId, lastname, genderid)
List<m_employees> Items = new List<m_employees>
{
new m_employees{ employeeid = 1, lastname = "mike", genderid = 1 },
new m_employees{ employeeid = 2, lastname = "jeni", genderid = 2 }
};
then i have my gender class columns (id, title)
List<m_genders> genders = new List<m_genders>
{
new m_genders{ id = 1, title = "Male" },
new m_genders{ id = 2, title = "Female" }
};
//then i tried joining the retrieved list of employees to the genders
var x = from emp in Items
join sex in genders
on emp.genderid equals sex.id
into a from b in a.DefaultIfEmpty(new m_genders())
select new
{
emp.lastname,
emp.genderid,
sex = b.title
};
red error line is showing to the keyword join and says "the type of one of the expressions in the join clause is incorrect..."
how can i join them properly?
This happens because types emp.genderid, sex.id are different and you need to cast or convert them explicitly like that:
(int)emp.genderid equals sex.id
I was able to reproduce the error with the following class definition:
class m_genders
{
public int id { get; set; }
public string title { get; set; }
}
class employee
{
public int id;
public uint genderid;
public string lastname { get; set; }
}
Your question is not clear, the code work without any problem :
namespace WindowsFormsApp1
{
public class m_genders
{
public int id;
public string title;
}
public class m_employees
{
public int employeeid { get; set; }
public int genderid { get; set; }
public string lastname { get; set; }
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
List<m_genders> genders = new List<m_genders>
{
new m_genders {id = 1, title = "Male"},
new m_genders {id = 2, title = "Female"}
};
List<m_employees> Items = new List<m_employees>
{
new m_employees{ employeeid = 1, lastname = "mike", genderid = 1 },
new m_employees{ employeeid = 2, lastname = "jeni", genderid = 2 }
};
var x = from emp in Items
join sex in genders
on emp.genderid equals sex.id
into a
from b in a.DefaultIfEmpty(new m_genders())
select new
{
emp.lastname,
emp.genderid,
sex = b.title
};
}
}
}
I need a little help in converting SQL to Linq. It's pretty straight forward in MySQL...
Table: customers
ID Name
1 Bill
2 John
Table: purchases
ID CustomerID CompletedTransaction
1 1 False
2 2 True
3 1 True
4 1 True
SELECT c.ID
c.Name,
COUNT(p.ID) AS TotalPurchases,
SUM(CASE WHEN p.CompletedTransaction = TRUE THEN 1 ELSE 0 END) AS TotalCompleted
FROM customers c
LEFT JOIN purchases p ON c.ID = p.CustomerID
GROUP BY c.ID
Expected Result:
1, Bill, 3, 2
2, John, 1, 1
I've seen a few examples on how to implement a left join in Linq but I'm not sure how to include a SUM and Count into this. I've seen examples in Linq where the fields returned are selected from the group keys. Does this mean that if I have more fields in the customers table such as address and other contact details which I'd like to return, I'd have to include them in the join to then be able to select them? Hope this makes sense. Appreciate any help or links that might point me in the right direction.
Thanks
var answer = (from c in db.customers
join p in db.purchases
on c.ID = p.CustomerID into subs
from sub in subs.DefaultIfEmpty()
group sub by new { c.ID, c.Name } into gr
select new {
gr.Key.ID,
gr.Key.Name,
Total = gr.Count(x => x != null),
CountCompleted = gr.Count(x => x != null && x.CompletedTransaction)
}).ToList();
Here's the sample
class Program
{
static void Main(string[] args)
{
List<Customers> customers = new List<Customers>();
customers.Add(new Customers() { ID = 1, Name = "Bill" });
customers.Add(new Customers() { ID = 2, Name = "John" });
List<Purchases> purchases = new List<Purchases>();
purchases.Add(new Purchases() { ID = 1, CustomerID = 1, CompletedTransaction = false });
purchases.Add(new Purchases() { ID = 2, CustomerID = 2, CompletedTransaction = true });
purchases.Add(new Purchases() { ID = 3, CustomerID = 1, CompletedTransaction = true });
purchases.Add(new Purchases() { ID = 4, CustomerID = 1, CompletedTransaction = true });
IEnumerable<JoinResult> results = from c in customers
join p in purchases
on c.ID equals p.CustomerID
group new { c, p } by new {p.CustomerID, c.Name} into r
select new JoinResult
{
CustomerID = r.Key.CustomerID,
CustomerName = r.Key.Name,
TotalPurchases = r.Count(),
TotalCompleteTransaction = r.Where(s=> s.p.CompletedTransaction).Count()
};
foreach(JoinResult r in results)
{
Console.WriteLine($"CustomerID : {r.CustomerID} | Name : {r.CustomerName} | TotalPurchases : {r.TotalPurchases} | TotalCompleteTransaction : {r.TotalCompleteTransaction}");
}
Console.ReadKey();
}
}
class Customers
{
public int ID { get; set; }
public string Name { get; set; }
}
class Purchases
{
public int ID { get; set; }
public int CustomerID { get; set; }
public bool CompletedTransaction { get; set; }
}
class JoinResult
{
public int CustomerID { get; set; }
public string CustomerName { get; set; }
public int TotalPurchases { get; set; }
public int TotalCompleteTransaction { get; set; }
}
Result
I have the following query and I am getting a null reference exception:
(from cec in _myContext.table1s
join ceclrp in _myContext.table2s on cec.table1ID equals ceclrp.table1ID
join lrp in _myContext.table3s on ceclrp.table3ID equals lrp.table3ID
join cecs in _myContext.table4s on cec.table1ID equals cecs.table1ID into cecsGroup
from ecService in cecsGroup.DefaultIfEmpty()
join cecse in _myContext.table5s on ecService.table4ID equals cecse.table4ID into cecseGroup
from ecServiceEntitlement in cecseGroup.DefaultIfEmpty()
where cec.ClientKey == clientKey
select new
{
table1 = cec,
table2 = ceclrp,
table3 = lrp,
table4 = ecService,
table5 = ecServiceEntitlement,
}).AsNoTracking();
Table 1, 2, and 3 records are required tables. However table 4 record is optional. If there is a table 4 record, then there can be an optional table 5 record.
However, I am getting a null reference exception when there is no table 4 or table 5 record.
I have looked at other questions similar to mine on StackOverflow but I can't figure out what is different from my query and the solutions posted.
Can someone please help me figure out why I am getting the null reference exception and what I need to do differently?
According to MSDN,
The default value for reference and nullable types is null.
For more than one LEFT JOIN, we can handle the null value by passing defaultValue for the DefaultIfEmpty() extension method. The following sample code works when I pass the default Constructor new Driver(), it throws exception if the defaultValue is removed.
Here I have created three models (Dealer, Model and Customer) with matching records and two models (Driver, DriverAddress) with optional records. The same as OP scenario.
So, passing the default value for the first LEFT JOIN may solve your problem.
public class Dealer
{
public int DealerId { get; set; }
public string Name { get; set; }
}
public class Model
{
public int ModelId { get; set; }
public string Name { get; set; }
public Dealer Dealer { get; set; }
}
public class Customer
{
public int CustomerId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Model Model { get; set; }
}
public class Driver
{
public int DriverId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Customer Customer { get; set; }
}
public class DriverAddress
{
public int DriverAddressId { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string Zip { get; set; }
public Driver Driver { get; set; }
}
class Program
{
static void Main(string[] args)
{
var honda = new Dealer { DealerId = 1, Name = "Honda" };
var ford = new Dealer { DealerId = 2, Name = "Ford" };
var toyoto = new Dealer { DealerId = 3, Name = "Toyoto" };
var volkswagen = new Dealer { DealerId = 4, Name = "Volkswagen" };
var chevrolet = new Dealer { DealerId = 5, Name = "Chevrolet" };
var civic = new Model { ModelId = 1, Name = "Civic", Dealer = honda };
var fiesta = new Model { ModelId = 2, Name = "Fiesta", Dealer = ford };
var corolla = new Model { ModelId = 3, Name = "Corolla", Dealer = toyoto };
var passat = new Model { ModelId = 4, Name = "Passat", Dealer = volkswagen };
var cruze = new Model { ModelId = 5, Name = "Cruze", Dealer = chevrolet };
var magnus = new Customer { CustomerId = 1, FirstName = "Magnus", LastName = "Hedlund", Model = civic };
var terry = new Customer { CustomerId = 2, FirstName = "Terry", LastName = "Adams", Model = fiesta };
var charlotte = new Customer { CustomerId = 3, FirstName = "Charlotte", LastName = "Weiss", Model = corolla };
var john = new Customer { CustomerId = 4, FirstName = "John", LastName = "Miller", Model = passat };
var arlene = new Customer { CustomerId = 5, FirstName = "Arlene", LastName = "Huff", Model = cruze };
var driver1 = new Driver { DriverId = 1, FirstName = "Fadi", LastName = "Fakhouri", Customer = magnus };
var driver2 = new Driver { DriverId = 2, FirstName = "Hanying", LastName = "Feng", Customer = terry };
var driver3 = new Driver { DriverId = 3, FirstName = "Cesar", LastName = "Garcia", Customer = charlotte };
var driver4 = new Driver { DriverId = 4, FirstName = "Lint", LastName = "Tucker", Customer = magnus };
var driver5 = new Driver { DriverId = 5, FirstName = "Robert", LastName = "Thomas", Customer = arlene };
var driver6 = new Driver { DriverId = 6, FirstName = "David", LastName = "Adams", Customer = charlotte };
var driver1Address = new DriverAddress { DriverAddressId = 1, AddressLine1 = "Main St", City = "Minnehaha", Zip = "57105", Driver = driver1 };
var driver2Address = new DriverAddress { DriverAddressId = 2, AddressLine1 = "State St", City = "Los Angeles", Zip = "90034", Driver = driver2 };
var driver3Address = new DriverAddress { DriverAddressId = 3, AddressLine1 = "Ralph St", City = "Winnebago", Zip = "61109", Driver = driver4 };
List<Dealer> lstDealers = new List<Dealer> { honda, ford, toyoto, volkswagen, chevrolet };
List<Model> lstModels = new List<Model> { civic, fiesta, corolla, passat, cruze };
List<Customer> lstCustomers = new List<Customer> { magnus, terry, charlotte, john, arlene };
List<Driver> lstDrivers = new List<Driver> { driver1, driver2, driver3, driver4, driver5, driver6 };
List<DriverAddress> lstDriverAddress = new List<DriverAddress> { driver1Address, driver2Address, driver3Address };
var result = from dealer in lstDealers
join model in lstModels on dealer.DealerId equals model.Dealer.DealerId
join customer in lstCustomers on model.ModelId equals customer.Model.ModelId
join driver in lstDrivers on customer.CustomerId equals driver.Customer.CustomerId into customerDriverGroup
from customerDriver in customerDriverGroup.DefaultIfEmpty(new Driver()) //defaultValue the empty constructor passed here
join address in lstDriverAddress on customerDriver.DriverId equals address.Driver.DriverId into driverAddressGroup
from driverAddress in driverAddressGroup.DefaultIfEmpty()
select new
{
Dealer = dealer,
Model = model,
Customer = customer,
Driver = customerDriver,
DriverAddress = driverAddress
};
foreach (var v in result)
{
Console.WriteLine("{0,-15}{1,-15}{2,-15}{3,-15}{4}", v.Dealer.Name + ":",
v.Model.Name + ":", v.Customer.FirstName + ":", v.Driver == null ? String.Empty : v.Driver.FirstName
+ ":", v.DriverAddress == null ? string.Empty : v.DriverAddress.City);
}
Console.Read();
}
}
You should check if your select new {... } values are null
Like:
select new
{
table1 = cec,
table2 = ceclrp,
table3 = lrp,
table4 = (ecService == null ? string.Empty : ecService),
table5 = (ecServiceEntitlement == null ? string.Empty : ecServiceEntitlement),
}).AsNoTracking();
This might be the problem.
join cecse in _myContext.table5s on ecService.table4ID equals cecse.table4ID into cecseGroup
When ecService == null, ecService .table4ID will cause a Null reference exception
Can you try this instead.
join cecse in _myContext.table5s on (ecService == null? 0 : ecService.table4ID) equals cecse.table4ID into cecseGroup
you can change 0 to any integer value which is not used in _myContext.table4s.table4ID. So your query would look like this.
(from cec in _myContext.table1s
join ceclrp in _myContext.table2s on cec.table1ID equals ceclrp.table1ID
join lrp in _myContext.table3s on ceclrp.table3ID equals lrp.table3ID
join cecs in _myContext.table4s on cec.table1ID equals cecs.table1ID into cecsGroup
from ecService in cecsGroup.DefaultIfEmpty()
join cecse in _myContext.table5s on (ecService == null? 0 : ecService.table4ID) equals cecse.table4ID into cecseGroup
from ecServiceEntitlement in cecseGroup.DefaultIfEmpty()
where cec.ClientKey == clientKey
select new
{
table1 = cec,
table2 = ceclrp,
table3 = lrp,
table4 = ecService,
table5 = ecServiceEntitlement,
}).AsNoTracking();
I would just expand the cecse variable into a left outer join too. Like how we would have done it in raw SQL too.
(from cec in _myContext.table1s
join ceclrp in _myContext.table2s on cec.table1ID equals ceclrp.table1ID
join lrp in _myContext.table3s on ceclrp.table3ID equals lrp.table3ID
join cecs in _myContext.table4s on cec.table1ID equals cecs.table1ID into cecsGroup
from ecService in cecsGroup.DefaultIfEmpty()
from cecse in _myContext.table5s.DefaultIfEmpty() // <---- here
from ecServiceEntitlement in cecseGroup.DefaultIfEmpty()
where cec.ClientKey == clientKey
&& ecService.table4ID equals cecse.table4ID // <---- here
select new
{
table1 = cec,
table2 = ceclrp,
table3 = lrp,
table4 = ecService,
table5 = ecServiceEntitlement,
}).AsNoTracking();