2013-04-08 23 views
5

İstemci tarafında Linq İfadeleri kullanmak, Serileştirmek ve Sunucu Tarafında Çalıştırmak istiyorum. Kullanmak istediğim Bunun içinİfade Ağacı Serileştiricisi

: http://expressiontree.codeplex.com/

Ama onları Yürütme istediğiniz bir kendi WCF Çağrısı oturtulur. WCF Yakası'nda Çağrı Var demektir

:

ImageDTO[] GetImages(XElement exp); 

şimdi İstemci Yakası'nda bir IQueryable (hangi Linq ifadeler yürütebileceği) sahip olmak istiyorum, ve (gelen serverside IQueryable var veri acess katmanım, serileştirilmiş ifadeyi yürütmek istiyorum.

Ama bunun nasıl emin değilim ve herhangi Örnekler bulmuyorum ...

i bir Sınıfında sorgusu uygulamak gerektiğini düşünüyorum İstemci Tarafında

, bu sınıf ben Oluşturucu anlatmak QueryProvider uygulamamı kullanmak için (WCF Hizmeti'ni aradığım yerden). Ama emin değilim eğer bu doğru ...

Belki bir kişi bir Örnek ile yardımcı olabilir. çerçevesinde IQueryable<T> bir uygulama var

+1

Sorunuza bir cevap değil, ama tecrübe, bunu ve bunun yerine özel bir iş servisleri yazmak olmaz. Karmaşıklık ekleyin ve müşterilerinizin sistemi yanlış sorgularla geri getirmesine izin verin. –

cevap

2

- sorguyu oluşturmak için istemci üzerinde bu kullanabiliyorsa MSDN: EnumerableQuery<T>

, sen IQueryable<T>.Expression özelliğinden bütün İfade Ağacı alabilirsiniz.

Bu Expression Tree Serializer ile çalışıp çalışmadığını görmek için bunu test etmeniz gerekir.

Daha sonra ifadeyi serileştirebilir, kabloya çarptırabilir ve daha sonra yeniden seri hale getirebilirsiniz.


Öyleyse sorun ifade ağacı bir EnumerableQuery<T> dayalı olmasıdır.

Yani adresinin IQueryable<T> kaynağı ile o değiştirmeniz gerekiyor senin Bu bitlik dağınık alır, ancak bir ExpressionVisitor:

IQueryable FixupExpressionTree(ObjectContext ctx, Type entityType, Expression expression) 
{ 
    var tObjectContext = ctx.GetType(); 
    var mCreateObjectSetOpen = tObjectContext.GetMethod("CreateObjectSet", new Type[ 0 ]); 
    var mCreateObjectSetClosed = mCreateObjectSetOpen.MakeGenericMethod(entityType); 

    var objectQuery = (ObjectQuery) mCreateObjectSetClosed.Invoke(ctx, null); 

    var eFixed = new Visitor(objectQuery, entityType).Visit(expression); 

    var qFixed = ((IQueryable) objectQuery).Provider.CreateQuery(eFixed); 

    return qFixed; 
} 

ve ExpressionVisitor kullanarak bir uygulama yazdım DbContext

gerçek kendisi:

public class Visitor : ExpressionVisitor 
{ 
    ObjectQuery _Source = null; 
    Type _EntityType = null; 

    public Visitor(ObjectQuery source, Type entityType) { _Source = source; _EntityType = entityType; } 

    protected override Expression VisitConstant(ConstantExpression node) 
    { 
     if (!node.Type.Name.Contains("EnumerableQuery")) return base.VisitConstant(node); 

     var eConstantInstance = Expression.Constant(_Source); 
     var eConstantArgument = Expression.Constant(MergeOption.AppendOnly); 

     var tObjectQueryOpen = typeof(ObjectQuery<>); 
     var tObjectQueryClosed = tObjectQueryOpen.MakeGenericType(_EntityType); 
     var eMergeAsMethod = tObjectQueryClosed.GetMethod("MergeAs", BindingFlags.Instance | BindingFlags.NonPublic); 

     return Expression.Call(eConstantInstance, eMergeAsMethod, eConstantArgument); 
    } 
} 

Calli ng bu yalındır:

Type entityType = ... 
Expression expression = ... 
DbContext db = ... 

ObjectContext ctx = ((IObjectContextAdapter) db).ObjectContext; 

IQueryable query = FixupExpressionTree(ctx, entityType, expression); 
+0

Tamam, ve İfadeyi serileştirdiğimde ve Sunucuda Deserialize ettiğimde, onu DL Katmanımdan aldığım IQueryable'imle nasıl uygularım? –

+0

Jochen: YourIQueryable.Provider.CreateQuery (receivedExpression) .ToList() –

+0

@ JochenKühner Gecikme için özür dilerim. Yorumunuzu yanıtlamak için yayınımı güncelledim. –