دسته بندی ها
17:29 1399/11/03

رفع خطای The LINQ expression could not be translated هنگام استفاده از دستور Contains

مشخصات سوال کننده :
کاربر : hamid_b     امتیاز کاربر : 518     رتبه کاربر : 4
دسته بندی : Asp.net Core Asp.net Mvc سی شارپ Entity Framework

به این سوال امتیاز بدهید    0
تعداد بازدید این سوال : 4229
هوش مصنوعی

پاسخ هوش مصنوعی

خطای شما به دلیل تغییرات در LINQ و Entity Framework در نسخه های جدیدتر است. در ASP.NET Core 3.1 و Entity Framework Core 3.1، برخی از قابلیت های LINQ به طور واضح نمی توانند به SQL ترجمه شوند، مانند این که شما یک آرایه از IDs را با استفاده از `Contains` در یک کویری به دست آمده از یک زیر پرس وجو مقایسه می کنید.

برای رفع این مشکل، می توانید به جای تبدیل لیست به آرایه و استفاده از `Contains`، مستقیماً از `Any()` استفاده کنید. کد شما به صورت زیر اصلاح می شود:

public List<ProductViewModel> ProductListForSearch(int drpcourse = -1)
{
     var Query = (from p in _context.Product_Tbl
                  select new ProductViewModel()
                  {
                     ProductID = p.ProductID,
                     ProductImage = p.ProductImage,
                     pGroupID = _context.ProductGroups_Tbl.Where(pg => pg.ProductID == p.ProductID).Select(s => s.GroupID).ToArray()
                   });
    if (drpcourse != -1)
    {
          Query = Query.Where(c => c.pGroupID.Any(id => id == drpcourse));
    }
    return Query.ToList();
}

با این تغییر، خطا برطرف خواهد شد و کویری شما در ASP.NET Core 3.1 به درستی کار خواهد کرد.

به این پاسخ امتیاز بدهید    0
امتیاز: - رتبه: -
پاسخ دهنده : saedbfd 19:20 1399/11/03

استفاده از دستور Contains در انتیتی فریم ورک 3.1

خطایی که شما دارید به این خاطر هست که در انتیتی فریم ورک نسخه 3.0 به بعد نسبت به انتیتی فریم ورک 2.2 تغییراتی وجود داشته. دستور زیر رو که شما در Core 2.2 استفاده می کردید و به درستی هم جواب میداده رو در نظر بگیرید :

Query = Query.Where(c => c.pGroupID.Contains(drpcourse));

خب در این دستور همه اطلاعات از دیتابیس واکشی شده و به روی سرور منتقل میشه و در سرور با توجه به دستور Contains اطلاعات فیلتر میشه و خروجی نمایش داده میشه. این چیزی هست که در Core 2.2 انجام میشه. اما یک اشکال داره و اونم این هست که باید همه اطلاعات به سرور بیاد و در سرور فیلتر بشه و خروجی مورد نظر نمایش داده بشه. خب این جا بار اضافی داره بر روی سرور تحمیل میشه. در انتیتی فریم ورک نسخه 3.0 به بعد برای این مشکل راه حل دادن و دلیل خطای شما هم همین هست.

در انتیتی فریم ورک نسخه  3.0 به بعد client evaluation پشتیبانی نمیشه. یعنی اطلاعات رو نمیشه فرستاد روی سرور و حافظه سرور و بعد جستجو کرد.

 

استفاده از متد AsEnumerable در انتیتی فریم ورک

اما راه حلی که در انتیتی فریم ورم 3.0 به بعد برای استفاده از متد Contains وجود داره این هست که از متد AsEnumerable استفاده بشه. وقتی از این متد استفاده می کنید کوئری شما در سمت دیتابیس اجرا میشه و فقط نتیجه به سمت سرور برگردانده میشه. این روش بازدهی بسیار بهتری در داده های زیاد دارد.

 

در نتیجه کوئری شما به این شکل باید تغییر کنه 

public List<ProductViewModel> ProductListForSearch(int drpcourse = -1)
{
     var Query = (from p in _context.Product_Tbl
                  select new ProductViewModel()
                  {
                     ProductID = p.ProductID,
                     ProductImage = p.ProductImage,
                     pGroupID = _context.ProductGroups_Tbl.Where(pg => pg.ProductID == p.ProductID).Select(s => s.GroupID).ToArray()
                   }).AsEnumerable();
    if (drpcourse != -1)
    {
          Query = Query.Where(c => c.pGroupID.Contains(drpcourse));
    }
    return Query.ToList();
}

 

به این پاسخ امتیاز بدهید    0
امتیاز: 1664 رتبه: 1
برای ارسال پاسخ لطفا وارد حساب کاربری خود شوید.   ورود