Почему 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();