Kısa cevap
Sen de aynı koleksiyona değerlendirecek şekilde uygulamanızda daha okunabilir ve sürdürülebilir olduğunu hissetmek yapmalı. derleyici yalnızca bir temsilci ve bir derleyici oluşturulan yöntemi oluşturmak gerekiyor edecek tek yüklem ifadesi olmadığı için
Uzun cevapoldukça uzun
Linq To Bu örnek için
ATable.Where(x=> condition1 && condition2 && condition3)
Nesneleri . reflektör itibaren
if (CS$<>9__CachedAnonymousMethodDelegate4 == null)
{
CS$<>9__CachedAnonymousMethodDelegate4 = new Func<ATable, bool>(null, (IntPtr) <Main>b__0);
}
Enumerable.Where<ATable>(tables, CS$<>9__CachedAnonymousMethodDelegate4).ToList<ATable>();
derleyici oluşturulan yöntemi:
[CompilerGenerated]
private static bool <Main>b__0(ATable m)
{
return ((m.Prop1 && m.Prop2) && m.Prop3);
}
yalnızca bir Where
uzatma yöntemi vardı beri beklendiği gibi temsilci ile Enumerable.Where<T>
içine sadece bir arama olduğunda görebileceğiniz gibi . Bu örnek için şimdi çok daha fazla kod üretildi
ATable.Where(x=>condition1).Where(x=>condition2).Where(x=>condition3)
. üç zincirleme Uzatma yöntemleri var yana
if (CS$<>9__CachedAnonymousMethodDelegate5 == null)
{
CS$<>9__CachedAnonymousMethodDelegate5 = new Func<ATable, bool>(null, (IntPtr) <Main>b__1);
}
if (CS$<>9__CachedAnonymousMethodDelegate6 == null)
{
CS$<>9__CachedAnonymousMethodDelegate6 = new Func<ATable, bool>(null, (IntPtr) <Main>b__2);
}
if (CS$<>9__CachedAnonymousMethodDelegate7 == null)
{
CS$<>9__CachedAnonymousMethodDelegate7 = new Func<ATable, bool>(null, (IntPtr) <Main>b__3);
}
Enumerable.Where<ATable>(Enumerable.Where<ATable>(Enumerable.Where<ATable>(tables, CS$<>9__CachedAnonymousMethodDelegate5), CS$<>9__CachedAnonymousMethodDelegate6), CS$<>9__CachedAnonymousMethodDelegate7).ToList<ATable>();
biz de üç Func<T>
s almak ve ayrıca üç derleyici oluşturulan yöntemler.
[CompilerGenerated]
private static bool <Main>b__1(ATable m)
{
return m.Prop1;
}
[CompilerGenerated]
private static bool <Main>b__2(ATable m)
{
return m.Prop2;
}
[CompilerGenerated]
private static bool <Main>b__3(ATable m)
{
return m.Prop3;
}
Şimdi bu daha yavaş olmalı, çünkü heck daha ton oluyor. Ancak, tüm yürütme GetEnumerator()
aranana kadar ertelendiğinden, fark edilebilir bir farkın kendini göstereceğinden şüphe duyuyorum.
performans
Linq biz IQueryable<T>
şimdi bizim derleyici oluşturulan kodu kullanarak bu yana biraz daha farklıdır.
var allInOneWhere = entityFrameworkEntities.MovieSets.Where(m => m.Name == "The Matrix" && m.Id == 10 && m.GenreType_Value == 3);
Bu, bir deyim oluşturuyor.
IQueryable<MovieSet> allInOneWhere = Queryable.Where<MovieSet>(entityFrameworkEntities.MovieSets, Expression.Lambda<Func<MovieSet, bool>>(Expression.AndAlso(Expression.AndAlso(Expression.Equal(Expression.Property(CS$0$0000 = Expression.Parameter(typeof(MovieSet), "m"), (MethodInfo) methodof(MovieSet.get_Name)), ..tons more stuff...ParameterExpression[] { CS$0$0000 }));
en önemli biz Expression.AndAlso
parçalara aşağı ayrıştırılır tek İfade ağacının ile bitirmek olmasıdır. Ve beklenen da benzeri sadece ben yolu uzun, bunun için derleyici kod yapıştırma rahatsız bile alışkanlık Queryable.Where
var chainedWhere = entityFrameworkEntities.MovieSets.Where(m => m.Name == "The Matrix").Where(m => m.Id == 10).Where(m => m.GenreType_Value == 3);
bir telefon var. Ama kısaca, Queryable.Where(Queryable.Where(Queryable.Where()))
'a üç çağrı ve üç ifade ile sonuçlanıyoruz. Bu, üç zincirli Where
maddesi olduğu için tekrar bekleniyor. listeleyicisi denir dek IEnumerable<T>
IQueryable<T>
gibi Sql
Oluşturulan
da yürütmüyor.
SELECT
[Extent1].[AtStore_Id] AS [AtStore_Id],
[Extent1].[GenreType_Value] AS [GenreType_Value],
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name]
FROM [dbo].[MovieSet] AS [Extent1]
WHERE (N'The Matrix' = [Extent1].[Name]) AND (10 = [Extent1].[Id]) AND (3 = [Extent1].[GenreType_Value])
performans etkisi olabilir Bazı Sorunlar
- zincirinde GetEnumerator metoduna yapılacak herhangi bir çağrı çağrı neden olur: Bu nedenle biz de aynı tam sql deyimi üretmek olduğunu bilmek mutlu olabilir sql için, örneğin
ATable.Where().ToList().Where()
aslında ilk yüklemeyle eşleşen tüm kayıtlar için sql'yi sorgulayacak ve ardından listeyi linq ile ikinci yüklemeyle nesnelere filtreleyecektir. Başka kullanmak yüklemler ayıklanması söz yana
- nerede, onlar
Expression<Func<T, bool>>
üstelik bu sadece Func<T, bool>
şeklindedir emin olun. İlk bir ifade ağacına ayrıştırılabilir ve geçerli sql'ye dönüştürülebilir, ikincisi TÜM OBJECTS döndürülür ve Func<T, bool>
bu koleksiyonda yürütülür.
Umarız bu, sorunuzu cevaplamak için biraz yardımcı oldu.
Derinlemesine cevap işareti için teşekkürler! :) – Joe
+1 Mükemmel bir yanıt için –
+1 müthiş bir cevap için teşekkürler –