2013-04-08 9 views
5

मैं क्लाइंट साइड पर लिंक अभिव्यक्तियों का उपयोग करना चाहता हूं, उन्हें सीरियलाइज़ करना और सर्वर साइड पर निष्पादित करना चाहता हूं।अभिव्यक्ति वृक्ष सीरिएलाइज़र

इस मैं का उपयोग करना चाहते के लिए: http://expressiontree.codeplex.com/

लेकिन मैं उन्हें निष्पादित करना चाहते हैं के खिलाफ एक खुद WCF कॉल।

इसका मतलब है कि मैं WCF साइड पर एक कॉल है:

ImageDTO[] GetImages(XElement exp); 

मैं अब क्लाइंट साइड पर एक IQueryable (जिस पर मैं Linq भाव निष्पादित कर सकते हैं) करना चाहते हैं, और मैं serverside पर एक IQueryable (से है मेरा डेटा एसेस लेयर, जिस पर मैं धारावाहिक अभिव्यक्ति निष्पादित करना चाहता हूं)।

लेकिन मैं ऐसा करने के तरीके यकीन नहीं है, और मैं किसी भी उदाहरण नहीं मिलता ...

क्लाइंट साइड मुझे लगता है कि मैं एक कक्षा में क्वेरी को लागू करना चाहिए पर, इस वर्ग मैं निर्माता में बता QueryProvider के मेरे कार्यान्वयन का उपयोग करने के लिए (जहां से मैं डब्ल्यूसीएफ सेवा कहता हूं)। लेकिन मुझे यकीन नहीं है कि यह सही है ...

शायद कोई उदाहरण के साथ मदद कर सकता है।

+1

मैं यह जानता हूँ अपने प्रश्न का उत्तर नहीं है, लेकिन अनुभव से, मैं यह कर नहीं होगा और बदले में समर्पित व्यापार सेवाओं लिखें। आप जटिलता जोड़ते हैं, और अपने ग्राहकों को सिस्टम को खराब प्रश्नों के साथ लाने की अनुमति देते हैं। –

उत्तर

2

वहाँ ढांचे में IQueryable<T> के एक कार्यान्वयन है - MSDN: EnumerableQuery<T>

आप क्वेरी बनाने के लिए ग्राहक पर इसका उपयोग कर सकते हैं, तो आप IQueryable<T>.Expression संपत्ति से पूरे अभिव्यक्ति ट्री मिल सकती है।

आपको यह देखने के लिए परीक्षण करना होगा कि यह अभिव्यक्ति वृक्ष Serializer के साथ काम करता है या नहीं।

var iQueryable = new EnumerableQuery<Model>(Enumerable.Empty<Model>()); 

var query = iQueryable.Include(...).Where(...).OrderBy(...); 

var expressionTree = query.Expression; 

आप अभिव्यक्ति को क्रमबद्ध कर सकते हैं, तार के पार इसे घुमा सकते हैं और फिर इसे deserialize कर सकते हैं।


तब समस्या यह है कि अभिव्यक्ति पेड़ EnumerableQuery<T> पर आधारित है।

तो तुम से बदलने के लिए है कि अपने IQueryable<T> स्रोत के साथ की जरूरत है अपने असली DbContext

यह एक बिट गंदा हो जाता है, लेकिन मैं एक कार्यान्वयन एक 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; 
} 

और ExpressionVisitor का उपयोग कर लिखा है स्वयं:

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); 
    } 
} 

कैली एनजी इस सीधे आगे है:

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

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

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

ठीक है, और जब मैंने अभिव्यक्ति को क्रमबद्ध किया है, और सर्वर पर Deserialised, मैं अपने डीएल परत से मेरे IQueryable wich के खिलाफ इसे कैसे निष्पादित कर सकता हूं? –

+0

जोचेन: YourIQueryable.Provider.CreateQuery (प्राप्त एक्स्पेरेशन)। टोस्टिस्ट() –

+0

@ जोकनकुहरर देरी के लिए खेद है। मैंने आपकी टिप्पणी का जवाब देने के लिए अपनी पोस्ट अपडेट की है। –

1

मेरी समस्या को दूर करने मैं Interlinq इस्तेमाल किया है, लेकिन एक संस्करण है जो मैं काँटेदार, इतना है कि यह भी सिल्वरलाइट के साथ काम करता है।

https://github.com/jogibear9988/Interlinq-2

संबंधित मुद्दे