Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Dil Tümleşik Sorgusu (LINQ), birden çok veri kaynağını birleştiren veya karmaşık işleme yapan birçok karmaşık işleç içerir. Tüm LINQ işleçlerinin sunucu tarafında uygun çevirileri yoktur. Bazen, bir formdaki sorgu sunucuya çevrilir, ancak farklı bir biçimde yazılmışsa sonuç aynı olsa bile çevrilemez. Bu sayfada bazı karmaşık işleçler ve bunların desteklenen varyasyonları açıklanmaktadır. Gelecek sürümlerde daha fazla desen tanıyabilir ve karşılık gelen çevirilerini ekleyebiliriz. Çeviri desteğinin sağlayıcılar arasında farklılık gösterdiğini aklınızda bulundurmak da önemlidir. SqlServer'da çevrilen belirli bir sorgu SQLite veritabanları için çalışmayabilir.
Tavsiye
Bu makalenin örneğini GitHub'da görüntüleyebilirsiniz.
Katılın
LINQ Join işleci, her kaynağın anahtar seçicisini temel alarak iki veri kaynağını bağlamanıza olanak tanır ve anahtar eşleştiğinde bir değer tanımlama grubu oluşturur. İlişkisel veritabanlarına doğal olarak INNER JOIN
şeklinde çevrilir. LINQ Join'in dış ve iç anahtar seçicileri olsa da, veritabanı tek bir birleştirme koşulu gerektirir. Bu nedenle EF Core, dış anahtar seçicisini eşitlik için iç anahtar seçiciyle karşılaştırarak bir birleştirme koşulu oluşturur.
var query = from photo in context.Set<PersonPhoto>()
join person in context.Set<Person>()
on photo.PersonPhotoId equals person.PhotoId
select new { person, photo };
SELECT [p].[PersonId], [p].[Name], [p].[PhotoId], [p0].[PersonPhotoId], [p0].[Caption], [p0].[Photo]
FROM [PersonPhoto] AS [p0]
INNER JOIN [Person] AS [p] ON [p0].[PersonPhotoId] = [p].[PhotoId]
Ayrıca, anahtar seçiciler anonim türlerse EF Core eşitlik bileşeni açısından karşılaştırmak için bir birleştirme koşulu oluşturur.
var query = from photo in context.Set<PersonPhoto>()
join person in context.Set<Person>()
on new { Id = (int?)photo.PersonPhotoId, photo.Caption }
equals new { Id = person.PhotoId, Caption = "SN" }
select new { person, photo };
SELECT [p].[PersonId], [p].[Name], [p].[PhotoId], [p0].[PersonPhotoId], [p0].[Caption], [p0].[Photo]
FROM [PersonPhoto] AS [p0]
INNER JOIN [Person] AS [p] ON ([p0].[PersonPhotoId] = [p].[PhotoId] AND ([p0].[Caption] = N'SN'))
GrupBirleştir
LINQ GroupJoin işleci Join'e benzer iki veri kaynağını bağlamanıza olanak tanır, ancak dış öğeleri eşleştirmek için bir iç değerler grubu oluşturur. Aşağıdaki örnekte olduğu gibi bir sorgunun yürütülmesi Blog
& IEnumerable<Post>
sonucunu oluşturur. Veritabanları (özellikle ilişkisel veritabanları) istemci tarafı nesne koleksiyonunu temsil etmek için bir yönteme sahip olmadığından GroupJoin çoğu durumda sunucuya çevirmez. Özel seçici olmadan GroupJoin yapmak için sunucudan tüm verileri almanız gerekir (aşağıdaki ilk sorgu). Ancak seçici seçilen verileri sınırlandırıyorsa, tüm verilerin sunucudan getirilmesi performans sorunlarına neden olabilir (aşağıdaki ikinci sorgu). Bu nedenle EF Core GroupJoin'i çevirmez.
var query = from b in context.Set<Blog>()
join p in context.Set<Post>()
on b.BlogId equals p.BlogId into grouping
select new { b, grouping };
var query = from b in context.Set<Blog>()
join p in context.Set<Post>()
on b.BlogId equals p.BlogId into grouping
select new { b, Posts = grouping.Where(p => p.Content.Contains("EF")).ToList() };
SelectMany
LINQ SelectMany işleci, her dış öğe için bir koleksiyon seçici üzerinden numaralandırma yaparak, her veri kaynağından değer demetleri oluşturmanıza olanak tanır. Bir şekilde, birleştirmedir ancak herhangi bir koşul içermez, bu nedenle her dış öğe koleksiyon kaynağından bir öğeyle bağlanır. Koleksiyon seçicinin dış veri kaynağıyla ilişkisine bağlı olarak SelectMany, sunucu tarafında çeşitli farklı sorgulara çevrilebilir.
Koleksiyon seçici dışarısına referans vermiyor
Koleksiyon seçici dış kaynaktan hiçbir şeye başvurmuyorsa, sonuç her iki veri kaynağının kartezyen ürünüdür. İlişkisel veritabanlarında CROSS JOIN
olarak çevrilir.
var query = from b in context.Set<Blog>()
from p in context.Set<Post>()
select new { b, p };
SELECT [b].[BlogId], [b].[OwnerId], [b].[Rating], [b].[Url], [p].[PostId], [p].[AuthorId], [p].[BlogId], [p].[Content], [p].[Rating], [p].[Title]
FROM [Blogs] AS [b]
CROSS JOIN [Posts] AS [p]
Koleksiyon seçici, bir where yan tümcesinde dış arama referans alıyor.
Koleksiyon seçicinin dış öğeye başvuran where yan tümcesi olduğunda EF Core bunu bir veritabanı birleşimine çevirir ve koşulu birleştirme koşulu olarak kullanır. Normalde bu durum, koleksiyon seçici olarak dış öğede koleksiyon gezgini kullanılırken ortaya çıkar. Koleksiyon bir dış öğe için boşsa, bu dış öğe için hiçbir sonuç oluşturulmaz. Ancak koleksiyon seçiciye uygulanırsa DefaultIfEmpty
, dış öğe iç öğenin varsayılan değeriyle bağlanır. Bu ayrım nedeniyle, INNER JOIN
uygulandığında ve DefaultIfEmpty
ile LEFT JOIN
olmadığında bu tür sorgular DefaultIfEmpty
olarak çevrilir.
var query = from b in context.Set<Blog>()
from p in context.Set<Post>().Where(p => b.BlogId == p.BlogId)
select new { b, p };
var query2 = from b in context.Set<Blog>()
from p in context.Set<Post>().Where(p => b.BlogId == p.BlogId).DefaultIfEmpty()
select new { b, p };
SELECT [b].[BlogId], [b].[OwnerId], [b].[Rating], [b].[Url], [p].[PostId], [p].[AuthorId], [p].[BlogId], [p].[Content], [p].[Rating], [p].[Title]
FROM [Blogs] AS [b]
INNER JOIN [Posts] AS [p] ON [b].[BlogId] = [p].[BlogId]
SELECT [b].[BlogId], [b].[OwnerId], [b].[Rating], [b].[Url], [p].[PostId], [p].[AuthorId], [p].[BlogId], [p].[Content], [p].[Rating], [p].[Title]
FROM [Blogs] AS [b]
LEFT JOIN [Posts] AS [p] ON [b].[BlogId] = [p].[BlogId]
Koleksiyon seçicisi, bir durumsuz durumda dış referans verir.
Koleksiyon seçicisi where yan tümcesinde olmayan dış öğeye başvurduğunda (yukarıdaki örnekte olduğu gibi), veritabanı bağlantısına dönüştürülmüyor. Bu nedenle her dış öğe için koleksiyon seçiciyi değerlendirmemiz gerekir. Bu, birçok ilişkisel veritabanındaki APPLY
işlemlerine çevrilir. Koleksiyon bir dış öğe için boşsa, bu dış öğe için hiçbir sonuç oluşturulmaz. Ancak koleksiyon seçiciye uygulanırsa DefaultIfEmpty
, dış öğe iç öğenin varsayılan değeriyle bağlanır. Bu ayrım nedeniyle, CROSS APPLY
uygulandığında ve DefaultIfEmpty
ile OUTER APPLY
olmadığında bu tür sorgular DefaultIfEmpty
olarak çevrilir. SQLite gibi bazı veritabanları işleçleri desteklemediğinden APPLY
bu tür sorgular çevrilmeyebilir.
var query = from b in context.Set<Blog>()
from p in context.Set<Post>().Select(p => b.Url + "=>" + p.Title)
select new { b, p };
var query2 = from b in context.Set<Blog>()
from p in context.Set<Post>().Select(p => b.Url + "=>" + p.Title).DefaultIfEmpty()
select new { b, p };
SELECT [b].[BlogId], [b].[OwnerId], [b].[Rating], [b].[Url], ([b].[Url] + N'=>') + [p].[Title] AS [p]
FROM [Blogs] AS [b]
CROSS APPLY [Posts] AS [p]
SELECT [b].[BlogId], [b].[OwnerId], [b].[Rating], [b].[Url], ([b].[Url] + N'=>') + [p].[Title] AS [p]
FROM [Blogs] AS [b]
OUTER APPLY [Posts] AS [p]
Grupla
LINQ GroupBy işleçleri, IGrouping<TKey, TElement>
türünde bir sonuç oluşturur, burada TKey
ve TElement
herhangi bir tür olabilir. Ayrıca, IGrouping
IEnumerable<TElement>
uygulayarak, gruplandırmanın ardından herhangi bir LINQ işlecini kullanarak bunlar üzerinde işlem yapabileceğiniz anlamına gelir. Hiçbir veritabanı yapısı bir IGrouping
öğesini temsil edebileceğinden GroupBy işleçlerinin çoğu durumda çevirisi yoktur. Her gruba skaler döndüren bir toplama işleci uygulandığında, bu işlem ilişkisel veritabanlarında SQL'e GROUP BY
olarak çevrilebilir. SQL GROUP BY
de kısıtlayıcıdır. Yalnızca skaler değerlere göre gruplandırmanızı gerektirir. Projeksiyon yalnızca gruplandırma anahtar sütunlarını veya bir sütuna uygulanan herhangi bir toplamayı içerebilir. EF Core bu deseni tanımlar ve aşağıdaki örnekte olduğu gibi sunucuya çevirir:
var query = from p in context.Set<Post>()
group p by p.AuthorId
into g
select new { g.Key, Count = g.Count() };
SELECT [p].[AuthorId] AS [Key], COUNT(*) AS [Count]
FROM [Posts] AS [p]
GROUP BY [p].[AuthorId]
EF Core, gruplandırmadaki bir toplama işlecinin Where veya OrderBy (veya başka bir sıralama) LINQ işlecinde göründüğü sorguları da çevirir. SQL'de where yan tümcesi olarak HAVING
yan tümcesini kullanır. GroupBy işlecini uygulamadan önce sorgunun parçası, sunucuya çevrilebildiği sürece herhangi bir karmaşık sorgu olabilir. Ayrıca, bir gruplama sorgusuna toplama işleçleri uygulayarak sonuçta elde edilen kaynaktan gruplamaları kaldırdıktan sonra, tıpkı diğer sorgular gibi bunun üzerine sorgular oluşturabilirsiniz.
var query = from p in context.Set<Post>()
group p by p.AuthorId
into g
where g.Count() > 0
orderby g.Key
select new { g.Key, Count = g.Count() };
SELECT [p].[AuthorId] AS [Key], COUNT(*) AS [Count]
FROM [Posts] AS [p]
GROUP BY [p].[AuthorId]
HAVING COUNT(*) > 0
ORDER BY [p].[AuthorId]
EF Core'un desteklediği toplama işleçleri aşağıdaki gibidir
.NET | SQL |
---|---|
Ortalama(x => x.Özellik) | AVG(Özellik) |
Count() | COUNT(*) |
LongCount() | COUNT(*) |
Max(x => x.Property) | MAX(Özellik) |
Min(x => x.Özellik) | MIN(Özellik) |
Sum(x => x.Özellik) | SUM(Özellik) |
Ek toplama işleçleri desteklenebilir. Daha fazla işlev eşlemesi için sağlayıcı belgelerinize bakın.
bir öğesini temsil eden bir IGrouping
veritabanı yapısı olmasa da, bazı durumlarda EF Core 7.0 ve daha yeni sürümler, sonuçlar veritabanından döndürüldükten sonra gruplandırmalar oluşturabilir. Bu, ilgili koleksiyonları eklerken kullanılan işlecin çalışma şekline Include
benzer. Aşağıdaki LINQ sorgusu, sonuçları Price özelliğinin değerine göre gruplandırmak için GroupBy işlecini kullanır.
var query = context.Books.GroupBy(s => s.Price);
SELECT [b].[Price], [b].[Id], [b].[AuthorId]
FROM [Books] AS [b]
ORDER BY [b].[Price]
Bu durumda GroupBy işleci doğrudan SQL'deki bir GROUP BY
yan tümceye çevrilmiyor, bunun yerine EF Core, sonuçlar sunucudan döndürüldükten sonra gruplandırmaları oluşturur.
Sol Birleştirme
Left Join bir LINQ işleci olmasa da ilişkisel veritabanlarında sorgularda sık kullanılan Bir Sol Birleştirme kavramı vardır. LINQ sorgularındaki belirli bir desen, sunucudaki ile LEFT JOIN
aynı sonucu verir. EF Core bu tür desenleri tanımlar ve sunucu tarafında eşdeğerini LEFT JOIN
oluşturur. Desen, her iki veri kaynağı arasında bir GroupJoin oluşturmayı ve ardından iç öğeye ilişkin bir öğe bulunmadığında null ile eşleşecek şekilde gruplandırma kaynağında DefaultIfEmpty ile SelectMany işlecini kullanarak gruplamayı düzleştirmeyi içerir. Aşağıdaki örnekte bu desenin nasıl göründüğü ve ne oluşturduğu gösterilmektedir.
var query = from b in context.Set<Blog>()
join p in context.Set<Post>()
on b.BlogId equals p.BlogId into grouping
from p in grouping.DefaultIfEmpty()
select new { b, p };
SELECT [b].[BlogId], [b].[OwnerId], [b].[Rating], [b].[Url], [p].[PostId], [p].[AuthorId], [p].[BlogId], [p].[Content], [p].[Rating], [p].[Title]
FROM [Blogs] AS [b]
LEFT JOIN [Posts] AS [p] ON [b].[BlogId] = [p].[BlogId]
Yukarıdaki desen, ifade ağacında karmaşık bir yapı oluşturur. Bu nedenle EF Core, işleci hemen izleyen bir adımda GroupJoin işlecinin gruplandırma sonuçlarını düzleştirmenizi gerektirir. GroupJoin-DefaultIfEmpty-SelectMany farklı bir desende kullanılsa bile, bunu Sol Birleşim olarak tanımlamayabiliriz.