2010-03-03 10 views
6

Linq sorgusuna bir İfadede geçmek, kullanılan sözdizimine bağlı olarak farklı davranır ve bunun neden böyle olduğunu merak ediyorum.Linq Burada anahtar kelime vs. Uzantı ve İfade parametrelerinin nerede olduğu

ı bu çok genel işlevi var diyelim

private IEnumerable<Company> 
    GetCompanies(Expression<Func<Company, bool>> whereClause) 
{ 
    return (from c in _ctx.Companies.Where(whereClause) select c); 
} 

beklenen Ama bu bir sonraki uygulama almaz (Delege 'System.Func' derleme değil Aşağıdaki uygulama çalışır
private IEnumerable<Company> 
    GetCompanies(Expression<Func<Company, bool>> whereClause) 

1 bağımsız değişkenler)

private IEnumerable<Company> 
    GetCompanies(Expression<Func<Company, bool>> whereClause) 
{ 
    return (from c in _ctx.Companies where whereClause select c); 
} 

Açıkçası İlk sözdizimini kullanabilirim, fakat derleyicinin niçin anahtar kelimenin Nerede uzantısı ile aynı olduğunu düşünmediğini merak ettim.

sayesinde Thomas

cevap

3

sözdizimi parametresini değiştirmek (tam gramer basitleştirilmesi) olduğu için çalışmaya ikinci kuvvet bir boole ifadesi değildir. Bu recitify için,

from c in _ctx.Companies where whereClause.Compile()(c) select c; 

whereClause olsaydı bir Func<Company, bool> Eğer

from c in _ctx.Companies where whereClause(c) select c; 

Not olduğunu

from x in e where f 

paçayı olabilir Not içine derleyici tarafından mekanik olarak çevrilmiştir söylemek zorunda

(from x in e).Where(x => f) 

Mekanik olarak diyorum çünkü bu çeviri, yöntem çağrılarının geçerliliğini kontrol etmek için herhangi bir semantik analiz yapmadan gerçekleştirir. Bu aşama, tüm sorgu ifadeleri LINQ yöntem çağırma ifadelerine çevrildikten sonra gelir. Özellikle

,

from c in _ctx.Companies where whereClause select c 

açıkça anlamsız olan bir

_ctx.Companies.Where(c => whereClause).Select(c) 

için çevrilir.IEnumerable<Company>.Where bir aşırı bir Func<Company, bool> kabul vardır ve Func<Company, bool> bir Expression<Func<Company, bool>> bir örtük dönüştürme olduğundan

from c in _ctx.Companies.Where(whereClause) select c 

okunaklı olması nedeni budur. Eğer LINQ sözdizimi kullandığınızda

private IEnumerable<Company> 
    GetCompanies(Expression<Func<Company, bool>> whereClause) 
{ 
    return _ctx.Companies.Where(whereClause); 
} 

, where fıkrada kodu bir kod ağacını temsil eden bir Expression<>, çevrilir:

+0

Eğer Func ifadesini Expression > yerine argüman olarak kabul edecekseniz, parametre olarak Predicate belgesini kullanmış olabilirsiniz. –

+0

Evet, bu yalnızca 'nerede' farklılıklarına odaklanmak için basitleştirilmiş bir örnektir. Bir İfadenin kullanılmasının nedeni >, bellekte değil, veri tabanında nerede yürütülmesini isteyeceğim. –

0

fark SQL benzeri o bool için değerlendirir ifadesini beklediğini nerede olduğudur. Ancak Nerede yönteminde ifade tipi delege olabilir.

Eğer

from identifier in expression where boolean-expression select expression 

whereClausewhereClause.Compile()(c) değiştirmek veya where madde içeren bir sorgu ekspresyonu için Func<Company, bool> whereClause ve whereClause(c)

2

Aslında her şeyi ile kısaltabilir. Expression<Func<Customer, bool>> kabul ettiğinizde, yönteminizin derleyici tarafından C# kodundan dönüştürülen bir kod ağacını kabul ettiğini söylüyorsunuz.

Kod ağacına zaten sahip olduğunuzdan, LINQ sözdizimini kullanmak yerine doğrudan Where() yöntemine iletmeniz gerekir.

+0

Evet Fark ettim ki, örneğim, farkın meydana geldiği yeri, yani nerede vs. diye hecelemek için yapıldı. Teşekkürler :). –