Почему 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();
}
}
7 ответов
Это не может быть преобразовано в SQL. Я думаю, теоретически это возможно, но не реализовано.
Вам просто нужно выполнить проекцию после получения результатов:
var pricingSecurityID = (from m in dbContext.Reporting_DailyNAV_Pricing
select m.PricingSecurityID).AsEnumerable()
.Select(x => new SelectListItem{ Text = x.ToString(), Value = x.ToString() });
Если это уже строка, зачем вам звонить ToString
на первом месте? Я подозреваю, что перевод не был включен в LINQ to Entities, потому что это бессмысленно. Измените выбранное предложение на:
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
).
Потому что он пытается преобразовать его в SQL, а он не может. Прекратить звонок ToString
и сделайте прогноз, прежде чем вернуться к звонящему. Итак, замените ваш select
пункт с
select m.PricingSecurityID
а потом сказать
return pricingSecurityID
.AsEnumerable()
.Select(x => x.ToString())
.Select(x => new SelectListItem { Text = x, Value = x })
.ToList();
Кроме того, я отмечаю, что вы смешиваете проблемы пользовательского интерфейса и проблемы запросов данных. Это вообще плохая практика. На самом деле, вы должны просто возвращать список идентификаторов и позволить части пользовательского интерфейса вашего кода беспокоиться о том, чтобы привести его в правильную форму.
Как насчет этого. В этом примере оба поля 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.
К сожалению, 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)
};
Я понимаю, что ответ на этот вопрос, и я согласен, что с помощью AsEnumerable()
это путь Однако я хотел бы выделить общий сценарий, с которым я обычно сталкиваюсь, когда AsEnumerable()
используется неэффективно для устранения этой ошибки.
Из .NET Language-Integrated Query для реляционных данных
Оператор 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
}
);
Try This using VB.NET, Important Point is you need to Get the results AsEnumerable as mentioned in Answers.
Dim _EventsDaysResult = From ED In TAdbContext.EventPolicies.AsEnumerable
Where ED.EventID = EID
Select New With {ED.EventID,
.DayInfo =
ED.EventDay.GetValueOrDefault.ToShortDateString & " ( " & ED.EventDayTitle & " ) "}
return dbContext.Reporting_DailyNAV_Pricing.AsEnumerable().Select(x => new SelectListItem
{
Text = x.PricingSecurityID.ToString(),
Value = x.PricingSecurityID.ToString()
}).ToList();