c# stored "لا يمكن تحويل تعبير لامدا مع نص عبارة إلى شجرة تعبير"



stored procedure entity framework (9)

استخدم هذا الزائد من تحديد:

Obj[] myArray = objects.Select(new Func<Obj,Obj>( o =>
{
    var someLocalVar = o.someVar;

    return new Obj() 
    { 
       Var1 = someLocalVar,
       Var2 = o.var2 
    };
})).ToArray();

https://src-bin.com

عند استخدام EntityFramework ، تظهر لي رسالة الخطأ " A lambda expression with a statement body cannot be converted to an expression tree " عند محاولة ترجمة التعليمة البرمجية التالية:

Obj[] myArray = objects.Select(o =>
{
    var someLocalVar = o.someVar;

    return new Obj() { 
    Var1 = someLocalVar,
    Var2 = o.var2 };
}).ToArray();

لا أعرف ماذا يعني الخطأ والأهم من ذلك كله كيفية إصلاحه. أي مساعدة؟


Answer #1

دون معرفة المزيد حول ما تقوم به (Linq2Objects، Linq2Entities، Linq2Sql؟) ، هذا يجب أن تعمل:

Arr[] myArray = objects.AsEnumerable().Select(o => {
    var someLocalVar = o.someVar;

    return new Obj() { 
        Var1 = someLocalVar,
        Var2 = o.var2 
    }; 
}).ToArray();

Answer #2

كان الكائن LINQ إلى SQL إرجاع تطبيق واجهة IQueryable . لذا ، لتحديد معلمة دالة Select يجب أن تقوم بتعبير تعبير لامدا واحد فقط بدون جسم.

هذا لأن LINQ لـ SQL البرمجية لا يتم تنفيذ البرنامج داخل بدلاً من جانب بعيد مثل SQL server أو الآخرين. تم تحقيق هذا النوع من التنفيذ عن طريق تطبيق IQueryable حيث يتم التفاف مندوبها في فئة نوع التعبير مثل أدناه.

Expression<Func<TParam,TResult>>

لا تدعم شجرة التعبير تعبير lambda مع الجسم var id = cols.Select( col => col.id ); lambda الوحيدة التي تدعم خط واحد مثل var id = cols.Select( col => col.id );

لذلك إذا حاولت أن يعمل الرمز التالي.

Expression<Func<int,int>> function = x => {
    return x * 2;
}

سوف تعمل التالية حسب المتوقع.

Expression<Func<int,int>> function = x => x * 2;

Answer #3

للحالة الخاصة بك ، فإن الجسم هو لإنشاء متغير ، والتبديل إلى IEnumerable سوف تجبر جميع العمليات المراد معالجتها على جانب العميل ، أقترح الحل التالي.

Obj[] myArray = objects
.Select(o => new
{
    SomeLocalVar = o.someVar, // You can even use any LINQ statement here
    Info = o,
}).Select(o => new Obj()
{
    Var1 = o.SomeLocalVar,
    Var2 = o.Info.var2,
    Var3 = o.SomeLocalVar.SubValue1,
    Var4 = o.SomeLocalVar.SubValue2,
}).ToArray();

تحرير: إعادة تسمية لاتفاقية C # Coding


Answer #4

هذا يعني أنه لا يمكنك استخدام تعبيرات lambda مع "جسم العبارة" (أي تعبيرات lambda التي تستخدم الأقواس المتعرجة) في الأماكن التي يحتاج فيها تحويل lambda إلى شجرة تعبير (وهي على سبيل المثال الحالة عند استخدام linq2sql) .


Answer #5

هل Arr هو نوع أساسي من Obj ؟ هل توجد طبقة Obj؟ تعمل التعليمات البرمجية الخاصة بك فقط إذا كان Arr نوع أساسي من Obj. يمكنك تجربة ذلك بدلاً من ذلك:

Obj[] myArray = objects.Select(o =>
{
    var someLocalVar = o.someVar;

    return new Obj() 
    { 
       Var1 = someLocalVar,
       Var2 = o.var2 
    };
}).ToArray();

Answer #6

هل objects سياق قاعدة بيانات Linq-SQL؟ في هذه الحالة ، يمكنك فقط استخدام تعبيرات بسيطة على يمين المشغل =>. والسبب هو أن هذه التعبيرات لا يتم تنفيذها ، ولكن يتم تحويلها إلى SQL ليتم تنفيذها على قاعدة البيانات. جرب هذا

Arr[] myArray = objects.Select(o => new Obj() { 
    Var1 = o.someVar,
    Var2 = o.var2 
}).ToArray();

Answer #7

يعني أن تعبير لامدا من النوع TDelegate الذي يحتوي على ([parameters]) => { some code }; لا يمكن تحويلها إلى Expression<TDelegate> . إنها القاعدة.

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

Arr[] myArray = objects.Select(o => new Obj()
                {
                   Var1 = o.someVar,
                   Var2 = o.var2
                } ).ToArray();

Answer #8

يمكنك استخدام نص العبارة في تعبير lamba لمجموعات IEnumerable . جرب هذه:

Obj[] myArray = objects.AsEnumerable().Select(o =>
{
    var someLocalVar = o.someVar;

    return new Obj() 
    { 
        Var1 = someLocalVar,
        Var2 = o.var2 
    };
}).ToArray();

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





linq-to-entities