LINQ to Entities no reconoce el método ‘System.String Format (System.String, System.Object, System.Object)’

Tengo esta consulta linq:

private void GetReceivedInvoiceTasks(User user, List 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 }; } 

Sin embargo, tiene problemas. Estoy tratando de crear tareas. Para cada nueva tarea cuando configuro el texto del enlace en una cadena constante como “Hola”, está bien. Sin embargo, más arriba estoy tratando de construir el texto de enlace de la propiedad usando las propiedades de la factura.

Me sale este error:

base {System.SystemException} = {“LINQ to Entities no reconoce el método ‘System.String Format (System.String, System.Object, System.Object)’, y este método no se puede traducir a una expresión de tienda.” }

Alguien sabe por qué? ¿Alguien sabe una forma alternativa de hacer esto para que funcione?

Entity Framework está tratando de ejecutar su proyección en el lado de SQL, donde no hay un equivalente a string.Format . Use AsEnumerable() para forzar la evaluación de esa parte con Linq to Objects.

Según la respuesta anterior que le he dado, reestructuraría su consulta de esta manera:

 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 }); 

También veo que usas entidades relacionadas en la consulta ( Organisation.Name ), asegúrate de agregar el Include apropiado a tu consulta, o materializa específicamente esas propiedades para su uso posterior, es decir:

 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 deriva de IEnumerable, el parecido principal es que cuando haces tu consulta se publica en el motor de la base de datos en su idioma, el momento débil es cuando le dices a C # que maneje los datos en el servidor (no al lado del cliente) o a SQL para manejar datos

Así que, básicamente, cuando dices IEnumerable.ToString (), C # obtiene la recostackción de datos y llama a ToString () en el objeto. Pero cuando dices IQueriable.ToString () C # le dice a SQL que llame a ToString () en el objeto, pero no existe dicho método en SQL.

El inconveniente es que cuando maneja datos en C #, toda la colección que está mirando a través de debe estar construida en la memoria antes de que C # aplique los filtros.

La manera más eficiente de hacerlo es hacer la consulta como IQueriable con todos los filtros que puede aplicar.

Y luego comstackrlo en la memoria y hacer que el formato de datos en C #.

 IQueryable 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") });