سؤال

هل هناك طريقة لاستخدام CompiledQuery.ترجمة طريقة تجميع التعبير المرتبطة IQueryable?حاليا لدي IQueryable كبير جدا التعبير شجرة وراء ذلك.IQueryable بنيت باستخدام عدة طرق كل توريد المكونات.على سبيل المثال ، طريقتين قد يعود IQueryables ثم انضم في المركز الثالث.لهذا السبب أنا لا يمكن أن تحدد بوضوح كامل التعبير في الترجمة() استدعاء الأسلوب.

كنت أتمنى أن تمر التعبير في تجميع الأسلوب كما someIQueryable.التعبير, ولكن هذا التعبير ليس في الشكل المطلوب من قبل تجميع الأسلوب.إذا كنت تحاول الحصول على حول هذا عن طريق وضع الاستعلام مباشرة إلى تجميع الأسلوب ، على سبيل المثال:

    var foo = CompiledQuery.Compile<DataContext, IQueryable<User>>(dc => dc.getUsers());
    var bar = foo(this);

حيث جعل المكالمة شكل داخل datacontext, أحصل على رسالة خطأ تقول أن "getUsers غير معين مثل إجراء مخزن أو دالة معرفة من قبل المستخدم".مرة أخرى أنا لا يمكن فقط نسخ محتويات getUsers الأسلوب حيث كنت جعل تجميع الدعوة منذ ذلك بدوره يجعل من استخدام أساليب أخرى.

هل هناك طريقة لتمرير التعبير على IQueryable عاد من "getUsers" في ترجمة الأسلوب ؟

تحديث حاولت قوة إرادتي على النظام مع التعليمات البرمجية التالية:

    var phony = Expression.Lambda<Func<DataContext, IQueryable<User>>>(
        getUsers().Expression, Expression.Parameter(typeof(DataContext), "dc"));

    Func<DataContext, IQueryable<User>> wishful = CompiledQuery.Compile<DataContext, IQueryable<User>>(phony);
    var foo = wishful(this);

فو ينتهي:

{System.البيانات.Linq.SqlClient.سقلبروفيدير+OneTimeEnumerable`1[نموذج.الكيانات.المستخدم]}

ليس لدي خيار لرؤية النتائج في فو ، بدلا من تقديم لتوسيع نتائج تشغيل الاستعلام أنا فقط انظر رسالة "عملية زعزعة استقرار وقت التشغيل".

أنا فقط بحاجة إلى العثور على طريقة سلسلة sql فقط تكون ولدت مرة واحدة و تستخدم paramaterized الأمر على الطلبات اللاحقة, يمكنني القيام بذلك يدويا باستخدام GetCommand الأسلوب على البيانات السياق ، ولكن بعد ذلك يجب أن بشكل صريح تعيين كافة المعلمات والقيام كائن رسم الخرائط نفسي ، الذي هو بضع مئات الأسطر من التعليمات البرمجية نظرا لتعقيد هذه استعلام معين.

تحديث

جون راسك توفير معلومات مفيدة للغاية لذا منحته الفوز على هذا واحد.بيد أن المزيد من التغيير والتبديل المطلوب وكانت هناك بضع قضايا أخرى واجهت على طول الطريق حتى ظننت أنني كنت "التوسيع" على الجواب.أولا, 'العملية يمكن أن destabalize وقت التشغيل' خطأ لم يكن بسبب تجميع التعبير ، كان في الواقع بسبب بعض الصب عميقة في التعبير شجرة.في بعض الأماكن أنا في حاجة إلى استدعاء .Cast<T>() طريقة رسميا يلقي البنود, حتى عندما كانوا من النوع الصحيح.دون الخوض في الكثير من التفاصيل هذا هو الأساس المطلوب عند عدة التعبير جنبا إلى جنب في شجرة واحدة وكل فرع العودة نوع مختلف ، والتي كانت كل نوع فرعي من فئة شيوعا.

بعد حل destabalizing المسألة عدت إلى تجميع المشكلة.جون توسيع الحل هو تقريبا هناك.بدا على استدعاء أسلوب التعبير في الشجرة و حاولت حلها الكامنة وراء التعبير هذا الأسلوب عادة العودة.بلدي الإشارات إلى عبارات لا تقدم طريقة المكالمات, ولكن بدلا من ذلك خصائص.لذلك أنا بحاجة إلى تعديل التعبير الزائر أن يؤدي التوسع لتشمل هذه الأنواع:

protected override Expression VisitMemberAccess(MemberExpression m) {
    if(m.Method.DeclaringType == typeof(ExpressionExtensions)) {
        return new ExpressionExpander().Visit((Expression)(((System.Reflection.PropertyInfo)m.Member).GetValue(null, null)));
    }
    return base.VisitMemberAccess(m);
}

هذه الطريقة قد لا تكون مناسبة في جميع الحالات ، ولكن ينبغي أن تساعد أي شخص يجد نفسه في نفس المأزق.

هل كانت مفيدة؟

المحلول

شيء مثل هذا يعمل, على الأقل في الاختبارات:

Expression<Func<DataContext, IQueryable<User>> queryableExpression = GetUsers();
var expressionWithSomeAddedStuff = (DataContext dc) => from u in queryableExpression.Invoke(dc) where ....;
var expressionThatCanBeCompiled = expressionWithSomeAddedStuff.Expand();
var foo = CompiledQuery.Compile<DataContext, IQueryable<User>>(expressionThatCanBeCompiled);

هذا يبدو قليلا مطول, و ربما يكون هناك التحسينات التي يمكنك أن تجعل.

فهي النقطة الرئيسية هي أنه يستخدم في الاحتجاج وتوسيع الطرق من LinqKit.أنها في الأساس تتيح لك بناء الاستعلام من خلال تكوين ثم جمع النتيجة النهائية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top