LINQ to SQL: Multiple externa esquerda junta
-
06-07-2019 - |
Pergunta
Eu estou tendo alguns problemas para descobrir como usar mais de uma junção externa esquerda usando LINQ to SQL. Eu entendo como usar um LEFT JOIN externa. Estou usando VB.NET. Abaixo está a minha sintaxe SQL.
T-SQL
SELECT
o.OrderNumber,
v.VendorName,
s.StatusName
FROM
Orders o
LEFT OUTER JOIN Vendors v ON
v.Id = o.VendorId
LEFT OUTER JOIN Status s ON
s.Id = o.StatusId
WHERE
o.OrderNumber >= 100000 AND
o.OrderNumber <= 200000
Solução
Isto pode ser mais limpa ( Você não precisa de todas as declarações into
):
var query =
from order in dc.Orders
from vendor
in dc.Vendors
.Where(v => v.Id == order.VendorId)
.DefaultIfEmpty()
from status
in dc.Status
.Where(s => s.Id == order.StatusId)
.DefaultIfEmpty()
select new { Order = order, Vendor = vendor, Status = status }
//Vendor and Status properties will be null if the left join is null
Aqui está outro exemplo LEFT JOIN
var results =
from expense in expenseDataContext.ExpenseDtos
where expense.Id == expenseId //some expense id that was passed in
from category
// left join on categories table if exists
in expenseDataContext.CategoryDtos
.Where(c => c.Id == expense.CategoryId)
.DefaultIfEmpty()
// left join on expense type table if exists
from expenseType
in expenseDataContext.ExpenseTypeDtos
.Where(e => e.Id == expense.ExpenseTypeId)
.DefaultIfEmpty()
// left join on currency table if exists
from currency
in expenseDataContext.CurrencyDtos
.Where(c => c.CurrencyID == expense.FKCurrencyID)
.DefaultIfEmpty()
select new
{
Expense = expense,
// category will be null if join doesn't exist
Category = category,
// expensetype will be null if join doesn't exist
ExpenseType = expenseType,
// currency will be null if join doesn't exist
Currency = currency
}
Outras dicas
não tem acesso a VisualStudio (Eu estou no meu Mac), mas usando as informações do http://bhaidar.net/cs/archive/2007/08/01/left-outer-join-in-linq-to-sql aspx parece que você pode ser capaz de fazer algo parecido com isto:
var query = from o in dc.Orders
join v in dc.Vendors on o.VendorId equals v.Id into ov
from x in ov.DefaultIfEmpty()
join s in dc.Status on o.StatusId equals s.Id into os
from y in os.DefaultIfEmpty()
select new { o.OrderNumber, x.VendorName, y.StatusName }
Eu descobri como usar exterior múltipla esquerda junta-se em VB.NET usando LINQ to SQL:
Dim db As New ContractDataContext()
Dim query = From o In db.Orders _
Group Join v In db.Vendors _
On v.VendorNumber Equals o.VendorNumber _
Into ov = Group _
From x In ov.DefaultIfEmpty() _
Group Join s In db.Status _
On s.Id Equals o.StatusId Into os = Group _
From y In os.DefaultIfEmpty() _
Where o.OrderNumber >= 100000 And o.OrderNumber <= 200000 _
Select Vendor_Name = x.Name, _
Order_Number = o.OrderNumber, _
Status_Name = y.StatusName
Em VB.NET usando Function,
Dim query = From order In dc.Orders
From vendor In
dc.Vendors.Where(Function(v) v.Id = order.VendorId).DefaultIfEmpty()
From status In
dc.Status.Where(Function(s) s.Id = order.StatusId).DefaultIfEmpty()
Select Order = order, Vendor = vendor, Status = status
Eu acho que você deve ser capaz de seguir o método usado em este post . Parece realmente feio, mas eu acho que você poderia fazê-lo duas vezes e obter o resultado desejado.
Gostaria de saber se este é realmente um caso em que você seria melhor fora de usar DataContext.ExecuteCommand(...)
em vez de converter para LINQ.
Eu estou usando esta consulta linq para a minha candidatura. se este coincidir com sua exigência você pode se referir isso. Aqui eu juntaram-se (junção externa esquerda), com 3 mesas.
Dim result = (From csL In contractEntity.CSLogin.Where(Function(cs) cs.Login = login AndAlso cs.Password = password).DefaultIfEmpty
From usrT In contractEntity.UserType.Where(Function(uTyp) uTyp.UserTypeID = csL.UserTyp).DefaultIfEmpty ' <== makes join left join
From kunD In contractEntity.EmployeeMaster.Where(Function(kunDat) kunDat.CSLoginID = csL.CSLoginID).DefaultIfEmpty
Select New With {
.CSLoginID = csL.CSLoginID,
.UserType = csL.UserTyp}).ToList()