2011-04-04 26 views
30

Varlık çerçevesi ve linq ile dinamik sorgular oluşturmanın en iyi yolunun ne olduğunu bilmek isterim.Varlık çerçevesiyle dinamik sorgular oluşturma

Sıralama ve filtreleme için birçok parametreye sahip bir hizmet oluşturmak istiyorum (50'den fazla). Bunların doldurulacağı yer olan gui'den nesne alıyorum ... ve sorgu tek bir hizmet yönteminden gerçekleştirilecek.

Etrafıma baktım Ve ben dinamik olarak benim yöntemin sonunda infaz edilebilir bir dize oluşturabilir gördü. Bu şekilde pek sevmiyorum. Bunu yapmanın daha iyi bir yolu var mı? Tercihen derleme kontrolü ile güvenli yazın? Eğer varlık modeli sorgulamak için oluşturmak dinamik URI WCF Veri Hizmetleri ve hizmet yaratma içine bakmak olabilir

cevap

45

Bir adım adım IQueryable<T> yazabilirsiniz. o zaman şöyle bir sorgu inşa edebileceğini ... ... kullanıcı filtrelemek ister açıklamaktadır bir FilterDefinition sınıf var

public class FilterDefinition 
{ 
    public bool FilterByName { get; set; } 
    public string NameFrom { get; set; } 
    public string NameTo { get; set; } 

    public bool FilterByQuantity { get; set; } 
    public double QuantityFrom { get; set; } 
    public double QuantityTo { get; set; } 
} 

varsayarsak:

public IQueryable<SomeEntity> GetQuery(FilterDefinition filter) 
{ 
    IQueryable<SomeEntity> query = context.Set<SomeEntity>(); 
    // assuming that you return all records when nothing is specified in the filter 

    if (filter.FilterByName) 
     query = query.Where(t => 
      t.Name >= filter.NameFrom && t.Name <= filter.NameTo); 

    if (filter.FilterByQuantity) 
     query = query.Where(t => 
      t.Quantity >= filter.QuantityFrom && t.Quantity <= filter.QuantityTo); 

    return query; 
} 
+0

Teşekkürler, ama bu nasıl çalışır? Bu veritabanından tüm verileri çekin ve sonra adım adım istenen veri kümesine kadar daraltmak değil mi? – Eduard

+7

@ t-edd: Hayır, 'ertelenmiş yürütme' özelliğini kullanır (http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-execution.aspx). Bu, yukarıdaki örnekte yer alan "IQueryable " ifadesinin yalnızca verilerin nasıl filtreleneceğini açıklayan bir sorgu ifadesi olduğu anlamına gelir. Sorgunun gerçek yürütülmesi, örnekte hiç yoktur. Sorguyu daha sonra "açgözlü" operatöre "IQueryable ", örneğin 'query.ToList() 'yöntemine uygulayarak yürütürsünüz. Bu noktada - ve daha önce değil - sorgu ifadesi SQL'e çevrilir ve sunucuya gönderilir. – Slauma

+0

O kadar da iyi değil çünkü "SomeEntity" nin Ad ve Miktar alanlarına sahip olduğunu varsayarsak, bu yalnızca yarı dinamiktir. –

1

. Bildiğim

30

yalnızca diğer yolu filtre vaues dayalı bir IQueryable inşa etmek olurdu.

+0

Evet, ancak bu etkili performans bilge mi? Seçim ne zaman yapılır? ToList() çağrıldığında sonunda? Çok büyük bir veri kümesine sahip olduğumu düşünün .... – Eduard

+1

Hayır, yalnızca bir kez sorgulamak için ertelenmiş yürütmeyi kullandığı için bir performans vuruşu değil. – BrandonZeider

+0

+1 İyi cevaplar için teşekkür ederiz. – Eduard

4

Dinamik şartname ve dinamik kullanabilirsiniz sipariş. Onlar hakkında blog yazdım here ve here. Örneğin Aşağıda yardımcı olmalıdır sen-

 //Assume you're getting following values from search form. 
     string userSuppliedProperty = "AverageRating"; 
     OperationType userSuppliedOperationType = OperationType.GreaterThan; 
     var userSuppliedValue = 4.5; 

     //Create DynamicSpecification from these properties and pass it to repository. 
     var userFilter = new DynamicSpecification<Product>(userSuppliedProperty, userSuppliedOperationType, userSuppliedValue); 
     var filteredProducts = _repository.Get(userFilter); 

     //You can also combine two specifications using either And or Or operation 
     string userSuppliedProperty2 = "Category"; 
     OperationType userSuppliedOperationType2 = OperationType.EqualTo; 
     var userSuppliedValue2 = "Keyboard"; 
     var userFilter2 = new DynamicSpecification<Product>(userSuppliedProperty2, userSuppliedOperationType2, userSuppliedValue2); 

     var combinedFilter = userFilter.And(userFilter2); 
     var filteredProducts2 = _repository.Get(combinedFilter); 

     //and it support dynamic sorting 
     string userSuppliedOrderingProperty = "Category"; 
     OrderType userSuppliedOrderType = OrderType.Ascending; 
     var sortedFilteredProducts = _repository.Get(combinedFilter, o => o.InOrderOf(userSuppliedOrderingProperty, userSuppliedOrderType)); 

Sana alıyoruz arama nesne/DTO bilmem ama kolayca bir genel arama nesne/DTO oluşturabilir ve birkaç satırda GenericSpecification en nesnelerin zincirine eşleyebilirsiniz kodun Geçmişte bir WCF servisinde kullandım ve benim için çok iyi çalıştı.