Czy ktoś mógłby mi podać przykład wykonania operacji łączenia lewego za pomocą wyrażeń LINQ/lambda?Lewe sprzężenie za pomocą LINQ
Odpowiedz
Numer LINQ to SQL samples page na stronie MSDN zawiera przykład tego, jak to zrobić. Kod powinien być prawie identyczny dla LINQ do Objects.
Kluczem tutaj jest połączenie z DefaultIfEmpty
.
Dim q = From e In db.Employees _
Group Join o In db.Orders On e Equals o.Employee Into ords = Group _
From o In ords.DefaultIfEmpty _
Select New With {e.FirstName, e.LastName, .Order = o}
Jeśli potrzebujesz pomocy przy konwersji do C#, po prostu zapytaj.
Oto example of a left join w LINQ.
Na przykład:
IQueryable<aspnet_UsersInRole> q = db.aspnet_Roles
.Select(p => p.aspnet_UsersInRoles
.SingleOrDefault(x => x.UserId == iduser));
daje listę ról z członkostwa asp.net, z null, jeżeli nie pasuje do określonego użytkownika (klawisz iduser)
The Way I odkryłem, że lubię połączyć OuterCollection.SelectMany()
z InnerCollection.DefaultIfEmpty()
. Możesz uruchomić następujące ustawienia w LINQPad, używając trybu "C# Statement".
var teams = new[]
{
new { Id = 1, Name = "Tigers" },
new { Id = 2, Name = "Sharks" },
new { Id = 3, Name = "Rangers" },
};
var players = new[]
{
new { Name = "Abe", TeamId = 2},
new { Name = "Beth", TeamId = 4},
new { Name = "Chaz", TeamId = 1},
new { Name = "Dee", TeamId = 2},
};
// SelectMany generally aggregates a collection based upon a selector: from the outer item to
// a collection of the inner item. Adding .DefaultIfEmpty ensures that every outer item
// will map to something, even null. This circumstance makes the query a left outer join.
// Here we use a form of SelectMany with a second selector parameter that performs an
// an additional transformation from the (outer,inner) pair to an arbitrary value (an
// an anonymous type in this case.)
var teamAndPlayer = teams.SelectMany(
team =>
players
.Where(player => player.TeamId == team.Id)
.DefaultIfEmpty(),
(team, player) => new
{
Team = team.Name,
Player = player != null ? player.Name : null
});
teamAndPlayer.Dump();
// teamAndPlayer is:
// {
// {"Tigers", "Chaz"},
// {"Sharks", "Abe"},
// {"Sharks", "Dee"},
// {"Rangers", null}
// }
podczas eksperymentowania z tym, uważam, że czasami można pominąć zerową kontrolę player
w instancji anonimowego typu. Myślę, że tak jest w przypadku używania LINQ-SQL w bazie danych (zamiast tych tablic, które moim zdaniem powodują LINQ-do-obiektów lub coś takiego.) Myślę, że pominięcie kontroli zerowej działa w LINQ -to-SQL, ponieważ zapytanie jest tłumaczone na SQL LEFT OUTER JOIN
, które przechodzi bezpośrednio do łączenia wartości null z elementem zewnętrznym. (Zauważ, że wartość właściwości anonimowego obiektu musi być zerowa, więc jeśli chcesz bezpiecznie dołączyć int
, powiedzmy, potrzebujesz czegoś takiego jak: new { TeamId = (int?)player.TeamId }
.
dobrze próbowałem odtworzyć słynny lewy dołączyć gdzie klucz b jest zerowy, a wynik mam jest to metoda rozszerzenie (przy odrobinie wyobraźni można zmodyfikować go po prostu zrobić LEFT JOIN):
public static class extends
{
public static IEnumerable<T> LefJoinBNull<T, TKey>(this IEnumerable<T> source, IEnumerable<T> Target, Func<T, TKey> key)
{
if (source == null)
throw new ArgumentException("source is null");
return from s in source
join j in Target on key.Invoke(s) equals key.Invoke(j) into gg
from i in gg.DefaultIfEmpty()
where i == null
select s;
}
}
Wszyscy na pokład LINQ Lambda Express, – mquander
Haha Mimo to, zamiast oglądania tego. post get get hammered downvotes, myślałem, że przerobię pytanie w przyzwoitym języku angielskim, ponieważ w rzeczywistości wydaje się być prawidłowy język angielski: – Noldorin
@mquander: ::: Czyta oryginalny ve rsion of question ::: To i twój komentarz przyniósł chichot. – Brian