Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

341
Views
Diferencia entre cast y como dentro de una selección en LINQ

Este código arroja una excepción:

 var query = services .SomeQuery(bar).select(x => (Foo)x) .Where(x.PropertyOfFoo == FooState.SomeState); var result = query.ToList();

La excepción:

 Unable to cast the type... LINQ to Entities only supports casting EDM primitive or enumeration types.

Este código funciona:

 var query = services .SomeQuery(bar).select(x => x as Foo) .Where(x.PropertyOfFoo == FooState.SomeState); var result = query.ToList();

¿Por qué as permite la conversión y cast no?

Entiendo que as devolverá nulo y cast generará una excepción si alguna de las llamadas falla. Bueno. Pero cuando ejecuto este código:

 var query = services .SomeQuery(bar); var result = query.ToList();

Obtengo un resultado de consulta mucho más grande. ¿Por qué?

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

LINQ to Entities no es lo mismo que LINQ to Objects. Mientras que las funciones de LINQ to Objects pueden tomar cualquier delegado coincidente e invocarlo ciegamente como código C# normal, LINQ to Entities trata sus lambdas como árboles de expresión porque necesita comprender la semántica de esas lambdas (no solo su firma) y transformarlas en un equivalente consulta para su backend EF. Naturalmente, esto significa que LINQ to Entities no puede manejar todas las operaciones que LINQ to Objects sí puede.

Ahora, como dijiste, una diferencia entre lanzar y usar as es que lanzar lanza una excepción en caso de falla y as devuelve null . Pero hay una diferencia aún más importante entre los dos: una conversión aplicará cualquier conversión explícita personalizada potencial, mientras as simplemente intentará reinterpretar la referencia como otra cosa, ignorando cualquier conversión potencial.

Como comprenderá, una conversión es mucho más complicada que as , porque una conversión puede invocar un método personalizado (el explicit operator ) que el proveedor de LINQ no puede resolver fácilmente. Es probable que el proveedor simplemente no pueda examinar el código de la posible conversión personalizada (no sé lo suficiente sobre las limitaciones de los árboles de expresión), y mucho menos traducirlo para la fuente subyacente. Por lo tanto, LINQ to Entities elige permitir solo los casos as conversión más simples (básicamente, permite los casos en los que la lógica de conversión se conocía con anticipación y no puede ser un código de usuario personalizado).

over 4 years ago · Santiago Trujillo Report

0

Hay una diferencia importante entre las dos declaraciones que muestra que, más que nada (como las reglas de CLR), Entity Framework está profundamente involucrado aquí.

  1. x as Foo se traduce a SQL. EF puede hacer eso porque sabe que siempre devolverá un resultado, ya sea Foo o nulo. El SQL generado es monstruoso por cierto, pero hace el trabajo.

  2. (Foo)x no se traduce a SQL. EF sabe que no hay forma de crear objetos Foo para todas las x , como exige la semántica de conversión, y lanza una excepción.

Tenga en cuenta que EF aceptará foos.Select(f => (Bar)f) , porque siempre es posible crear un tipo base a partir de un subtipo. La conversión real se realiza después de que se recibe el resultado de SQL, no afecta al propio SQL.

También aceptará bars.OfType<Foo>().Select(x => (Foo)x) (aunque esto es bastante inútil).

Así que el mensaje de error...

LINQ to Entities solo admite la conversión de tipos primitivos o de enumeración de EDM.

... no es del todo cierto. EF acepta moldes cuando son factibles. Entonces, dentro del traductor de consultas de EF, solo hay un montón de lógica para decidir si vale la pena o no generar una declaración SQL.

over 4 years ago · Santiago Trujillo Report

0

Es una diferencia en cómo funciona la conversión directa frente a cómo funciona el operador as . La conversión directa no está disponible porque no está utilizando un tipo de valor; solo funciona para primitivos.

Ahora, su lambda está tratando de seleccionar y proyectar; podría dividir eso en dos operaciones, entonces:

 var result = services.SomeQuery(bar).select(x => new Foo() { SomeProperty = x.SomeProperty, SomeOtherProperty = x.SomeOtherProperty, ... }).ToList()

En cuanto a la mayor cantidad de resultados: te falta una cláusula where allí.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!