2012-03-03 29 views
5

içeren bir Linq ifadesi oluşturma Çalışma zamanı sırasında dinamik olarak Linq ifadeleri oluşturma sorunu üzerine güldüm. Çoğu örnekte, sadece belirli bir veri tabanı varlığının bir özelliğini tek bir parametreyle karşılaştırmanın oldukça basit bir görevini ele aldım. böylece gibi: ayrıca böyle çok daha genel bir yaklaşımla elde edilebilirDinamik olarak bir alt sorguyu

Session.Query.Where(m => m.Name.Contains("test")) 

: Ancak

var item = Expression.Parameter(typeof (MyClass), "item"); 
var property = Expression.Property(item, "Name"); 
var containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) }); 
var searchExpression = Expression.Constant(searchString, typeof(string)); 
var containsMethodExpression = Expression.Call(property, containsMethod, searchExpression); 
var lambda = Expression.Lambda<Func<MyClass, bool>>(containsMethodExpression, item); 
query = query.Where(lambda);  

bazen görev biraz daha karmaşıktır ve bir aşağıdaki gibi bir şey elde etmek istiyor:

Session.Query.Where(m => m.SpecialProperty.Any(f => f.Name.Contains("test"))); 

"SpecialProperty" tipi List <> ve mülkiyet "Ad" taşımaktadır

dize türünde olduğunu.

Dinamik olarak böyle bir Linq ifadesi oluşturmak mümkün mü ve bu nasıl başarılabilir? Bu yaklaşımla ilgili herhangi bir performans kaygısı var mı?

cevap

6

Özel kullanım durumumda çalışan bir çözüm buldu ve tam olarak aradığım şeyi yapıyor.

/* 
building expression tree 
example: Session.Query.Where(m => m.SpecialProperty.Any(f => f.Name.Contains("test"))) 
*/ 

var innerItem = Expression.Parameter(typeof(MyInnerClass), "f"); 
var innerProperty = Expression.Property(innerItem, "Name"); 
var innerMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) }); 
var innerSearchExpression = Expression.Constant(searchString, typeof(string)); 
var innerMethodExpression = Expression.Call(innerProperty, innerMethod, new[] { innerSearchExpression }); 
var innerLambda = Expression.Lambda<Func<MyInnerClass, bool>>(innerMethodExpression, innerItem); 

var outerItem = Expression.Parameter(typeof(MyOuterClass), "m"); 
var outerProperty = Expression.Property(outerItem, info.Name); 
/* calling a method extension defined in Enumerable */ 
var outerMethodExpression = Expression.Call(typeof(Enumerable), "Any", new[] { typeof(MyInnerClass) }, outerProperty, innerLambda); 
var outerLambda = Expression.Lambda<Func<MyOuterClass, bool>>(outerMethodExpression, outerItem); 
query = query.Where(outerLambda); 

Bu oldukça dowdy yaklaşım

türleri ve yöntem adları para- sağlamak için yerine daha şık bir hat LINQ İfade gereklidir. Ancak, elbette olası performans cezaları hakkındaki diğer önerileri ve fikirleri de düşünmüyorum.

Bu kod snippet'inin How to produce a Subquery using non-generic Lambda çözülmesinde de yardımcı olması olasıdır.

İlgili konular