Почему LINQ to Entities не распознает метод "System.String ToString()?

Получение ошибки внутри веб-приложения MVC3. LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression.

когда я пытаюсь извлечь значения с помощью EF из запроса:

public class DataRepository
    {
        public mydataEntities1 dbContext = new mydataEntities1();

        public List<SelectListItem> GetPricingSecurityID()
        {
        var pricingSecurityID = (from m in dbContext.Reporting_DailyNAV_Pricing
                                     select new SelectListItem
                                         {
                                                Text = m.PricingSecurityID.ToString(),
                                                Value = m.PricingSecurityID.ToString()
                                         });

        return pricingSecurityID.ToList();
        }
    }

Ответ 1

Это не может быть преобразовано в SQL. Я думаю, теоретически это возможно, но не реализовано.

Вам просто нужно выполнить свою проекцию после того, как у вас есть результаты:

var pricingSecurityID = (from m in dbContext.Reporting_DailyNAV_Pricing
                                     select m.PricingSecurityID).AsEnumerable()
    .Select(x => new SelectListItem{ Text = x.ToString(), Value = x.ToString() });

Ответ 2

Если это уже строка, почему вы беспокоитесь о вызове ToString в первую очередь? Я подозреваю, что перевод не был включен в LINQ для Entities, потому что это бессмысленно. Измените предложение select на:

select new SelectListItem
{
    Text = m.PricingSecurityID,
    Value = m.PricingSecurityID
}

Если вам действительно нужно сделать что-то, не поддерживаемое LINQ to Entities, используйте AsEnumerable для перехода от запроса к базе данных к процессу:

public List<SelectListItem> GetPricingSecurityID()
{
    return dbContext.Reporting_DailyNAV_Pricing
                    .Select(m => m.PricingSecurityID)
                    .AsEnumerable() // Rest of query is local
                    // Add calls to ToString() if you really need them...
                    .Select(id => new SelectListItem { Text = id, Value = id })
                    .ToList();
}

Я согласен с возражениями Джейсона, кстати. Вам лучше было бы вернуть List<string>, который отображается в другом месте.

Также обратите внимание, что если вы просто собираетесь использовать одно предложение select или просто предложение where, выражения запроса действительно не добавляют многого - вызов методов расширения LINQ может закончиться меньшим количеством помех, в частности если вы хотите вызывать методы, которые не поддерживаются в выражениях запроса (например, ToList).

Ответ 3

Потому что он пытается преобразовать его в SQL, и он не может. Отключите вызов до ToString и сделайте проецирование, прежде чем вы вернетесь к вызывающему. Итак, замените предложение select на

select m.PricingSecurityID

а затем скажите

return pricingSecurityID
           .AsEnumerable()
           .Select(x => x.ToString())
           .Select(x => new SelectListItem { Text = x, Value = x })
           .ToList();

Кроме того, я отмечаю, что вы смешиваете проблемы пользовательского интерфейса и проблемы с запросами данных. Это, как правило, плохая практика. На самом деле, вы должны просто вернуть список идентификаторов и позволить части пользовательского интерфейса вашего кода беспокоиться о том, чтобы отладить его в правильной форме.

Ответ 4

Как насчет этого. В этом примере как поле VDN в поле db, так и поле Skill являются целыми числами. Я ищу совпадения из обоих полей, поэтому у меня есть 2 сравнения.

Включите это:

using System.Data.Objects.SqlClient; // needed to convert numbers to strings for linq

При сравнении чисел выполните следующее:

        // Search Code
            if (!String.IsNullOrEmpty(searchString))
            {
                depts = depts.Where(d => SqlFunctions.StringConvert((double)d.VDN).Contains(searchString.ToUpper())
                || SqlFunctions.StringConvert((double)d.Skill).Contains(searchString.ToUpper()));
            }
        // End Search Code

Workie.

Ответ 5

Печально EF не знает, как преобразовать .ToString() Вы должны использовать встроенную функцию SqlFunctions.StringConvert: http://msdn.microsoft.com/en-us/library/dd466292.aspx Также нет перегрузка для int, поэтому вы должны привести к двойному: - (

var vendors = 
   from v in Vendors  
   select new
   {             
       Code = SqlFunctions.StringConvert((double)v.VendorId)
   }; 

Ответ 6

Я понимаю, что на этот вопрос ответили, и я согласен с тем, что использование AsEnumerable() - это путь. Однако я хотел бы выделить общий сценарий, с которым обычно сталкиваюсь, где AsEnumerable() используется неэффективно для устранения этой ошибки.

От . NET-интегрированный запрос для реляционных данных

Оператор AsEnumerable(), в отличие от ToList() и ToArray(), не вызывает выполнение запроса. Он все еще отложен. Оператор AsEnumerable() просто изменяет статическую типизацию запроса, превращая IQueryable в IEnumerable, обманывая компилятор, рассматривая остальную часть запроса как локально выполненную.

Ссылки

Неэффективный способ

IEnumerable<InvoiceDTO> inefficientEnumerable = 
     (from a in db.Invoices
     where a.Practice_Key == practiceKey.FirstOrDefault()
     select a
     ).AsEnumerable().
     Select(x => new InvoiceDTO
                             {
                                 InvoiceID = x.InvoiceID,
                                 PracticeShortName = x.Dim_Practice.Short_Name,
                                 InvoiceDate = x.InvoiceDate,
                                 InvoiceTotal = x.InvoiceAmount,
                                 IsApproved = x.IsApproved,
                                 InvoiceStatus = (
                                                  x.IsApproved == null ? "Pending" :
                                                  x.IsApproved == true ? "Approved" :
                                                  x.IsApproved == false ? "Rejected" : "Unknown"
                                                ),
                                 InvoicePeriodStartDateText = x.InvoicePeriodStart.ToShortDateString(),
                                 InvoicePeriodEndDateText = x.InvoicePeriodEnd.ToShortDateString(),
                                 InvoicePeriodStartDate = x.InvoicePeriodStart,
                                 InvoicePeriodEndDate = x.InvoicePeriodEnd
                             }
                             );

            invoices = inefficientEnumerable.ToList();

Здесь AsEnumerable используется для всей таблицы. Все столбцы выбираются, хотя они не нужны.

Лучший способ

 IQueryable<InvoiceDTO> invoicesQuery = 
   (from a in db.Invoices
   where a.Practice_Key == practiceKey.FirstOrDefault()
   select new InvoiceDTO
            {
             InvoiceID = a.InvoiceID,
             PracticeShortName = a.Dim_Practice.Short_Name,
             InvoiceDate = a.InvoiceDate,
             InvoiceTotal = a.InvoiceAmount,
             IsApproved = a.IsApproved,
             InvoiceStatus = (
                               a.IsApproved == null ? "Pending" :
                               a.IsApproved == true ? "Approved" :
                               a.IsApproved == false ? "Rejected" :"Unknown"
                               ),
             InvoicePeriodStartDate = a.InvoicePeriodStart,
             InvoicePeriodEndDate = a.InvoicePeriodEnd
          });


          IEnumerable<InvoiceDTO> betterEnumerable = invoicesQuery.AsEnumerable().
          Select(x => new InvoiceDTO
                                 {
                                     InvoiceID = x.InvoiceID,
                                     PracticeShortName = x.PracticeShortName,
                                     InvoiceDate = x.InvoiceDate,
                                     InvoiceTotal = x.InvoiceTotal,
                                     IsApproved = x.IsApproved,
                                     InvoiceStatus = x.InvoiceStatus,
                                     InvoicePeriodStartDateText = x.InvoicePeriodStartDate.ToShortDateString(),
                                     InvoicePeriodEndDateText = x.InvoicePeriodEndDate.ToShortDateString(),
                                     InvoicePeriodStartDate = x.InvoicePeriodStartDate,
                                     InvoicePeriodEndDate = x.InvoicePeriodEndDate
                                 }
                                 );

Ответ 7

Попробуйте сделать это с помощью VB.NET. Важно отметить, что вам нужно получить результаты AsEnumerable, как указано в разделе "Ответы".

Dim _EventsDaysResult = From ED In TAdbContext.EventPolicies.AsEnumerable
                                    Where ED.EventID = EID
                                    Select New With {ED.EventID, 
                                    .DayInfo = 
                                    ED.EventDay.GetValueOrDefault.ToShortDateString & " ( " & ED.EventDayTitle & " ) "}

Ответ 8

return dbContext.Reporting_DailyNAV_Pricing.AsEnumerable().Select(x => new SelectListItem
{
    Text = x.PricingSecurityID.ToString(),
    Value = x.PricingSecurityID.ToString()
}).ToList();