LINQ to Entities не распознает систему метода.Строковый Формат (System.Строка, Система.объектная система.Объект')
У меня есть этот запрос LINQ:
private void GetReceivedInvoiceTasks(User user, List<Task> tasks)
{
var areaIds = user.Areas.Select(x => x.AreaId).ToArray();
var taskList = from i in _db.Invoices
join a in _db.Areas on i.AreaId equals a.AreaId
where i.Status == InvoiceStatuses.Received && areaIds.Contains(a.AreaId)
select new Task {
LinkText = string.Format(Invoice {0} has been received from {1}, i.InvoiceNumber, i.Organisation.Name),
Link = Views.Edit
};
}
у него есть проблемы, хотя. Я пытаюсь создавать задачи. Для каждой новой задачи, когда я устанавливаю текст ссылки на постоянную строку, такую как" Hello", это нормально. Однако выше я пытаюсь построить свойство linktext, используя свойства счета-фактуры.
Я получаю эту ошибку:
base {System.SystemException} = {"LINQ to Entities не распознает метод' System.Строковый Формат (System.Строка, Система.Объект, Система.Метод объекта), и этот метод не может быть переведен в магазине выражение."}
кто-нибудь знает почему? Кто-нибудь знает альтернативный способ сделать это, чтобы заставить его работать?
2 ответа:
Entity Framework пытается выполнить вашу проекцию на стороне SQL, где нет эквивалента
string.Format
. ИспользуйтеAsEnumerable()
для принудительной оценки этой части с помощью Linq для объектов.на основе на предыдущий ответ Я дал вам я бы реструктурировать ваш запрос следующим образом:
int statusReceived = (int)InvoiceStatuses.Received; var areaIds = user.Areas.Select(x=> x.AreaId).ToArray(); var taskList = (from i in _db.Invoices where i.Status == statusReceived && areaIds.Contains(i.AreaId) select i) .AsEnumerable() .Select( x => new Task() { LinkText = string.Format("Invoice {0} has been received from {1}", x.InvoiceNumber, x.Organisation.Name), Link = Views.Edit });
также я вижу, что вы используете связанные сущности в запросе (
Organisation.Name
) убедитесь, что вы добавляете правильноеInclude
к вашему запросу, или конкретно материализовать эти свойства для последующего использования, т. е.:var taskList = (from i in _db.Invoices where i.Status == statusReceived && areaIds.Contains(i.AreaId) select new { i.InvoiceNumber, OrganisationName = i.Organisation.Name}) .AsEnumerable() .Select( x => new Task() { LinkText = string.Format("Invoice {0} has been received from {1}", x.InvoiceNumber, x.OrganisationName), Link = Views.Edit });
IQueriable происходит от IEnumerable, основное сходство заключается в том, что когда вы делаете свой запрос, он отправляется в компонент database engine на своем языке, тонкий момент-это когда вы говорите C# обрабатывать данные на сервере(а не на стороне клиента) или говорить SQL обрабатывать данные.
Так что в основном, когда вы говорите IEnumerable.ToString (), C# получает сбор данных и вызывает ToString () для объекта. Но когда вы говорите IQueriable.ToString () C# говорит SQL, чтобы вызвать ToString () на объекте, но там нет такого метода в SQL.
недостаток заключается в том, что при обработке данных в C# вся коллекция, которую вы ищете, должна быть создана в памяти до того, как C# применит фильтры.
наиболее эффективный способ сделать это-сделать запрос как IQueriable со всеми фильтрами, которые вы можете применить.
и затем построить его в памяти и форматирование данных в C#.
IQueryable<Customer> dataQuery = Customers.Where(c => c.ID < 100 && c.ZIP == 12345 && c.Name == "John Doe"); var inMemCollection = dataQuery.AsEnumerable().Select(c => new { c.ID c.Name, c.ZIP, c.DateRegisterred.ToString("dd,MMM,yyyy") });