2008-12-30 20 views
7

devuelve Tengo un LINQ a Entidades consulta como esta:LINQ lista o solo objeto

var results = from r in entities.MachineRevision 
       where r.Machine.IdMachine == pIdMachine 
       && r.Category == (int)pCategory 
       select r; 

Generalmente, utilizo el siguiente código para comprobar si se devuelven algunos resultados:

if (results.Count() > 0) 
{ 
    return new oMachineRevision(results.First().IdMachineRevision); 
} 

Sin embargo , Recibo NotSupportedException en la condición if. El mensaje de error es No se puede crear un valor constante de tipo 'Tipo de cierre'. En este contexto solo se admiten tipos primitivos ('como Int32, String y Guid').

Tenga en cuenta que pCategory es un tipo Enum.

Respuesta

11

EDIT: Según su actualización, el error puede estar relacionado con una enumeración en su clase de entidad. Consulte esto blog entry para obtener más información y una solución temporal. Dejo mi respuesta original como una mejora en la sintaxis de tu consulta.

Intenta hacer la selección de la primera entidad en la consulta misma usando FirstOrDefault y luego verifica si el resultado es nulo.

int compareCategory = (int)pCategory; // just a guess 
var result = (from r in entities.MachineRevision 
       where r.Machine.IdMachine == pIdMachine 
       && r.Category == compareCategory 
       select r).FirstOrDefault(); 

if (result != null) 
{ 
    return new oMachineRevision(result.IdMachineRevision); 
} 
+0

Todavía no funciona, porque estamos tratando de ejecutar el FirstOrDefault() método en un objeto entidad (eso es lo que devuelve la instrucción linq) y no un IEnumerable. –

+1

Seleccionar siempre devuelve un IEnumerable, consulte los documentos aquí http://msdn.microsoft.com/en-us/library/bb548891.aspx. ¿Estás seguro? ¿el ejemplo es exactamente el mismo que tu código? – tvanfosson

+0

Mi error, me disculpo por eso. Para simplificar el código, he eliminado una enumeración, al igual que tvanfosson notado por el mensaje de error que estaba recibiendo. Gracias a todos y disculpe por engañarlo. –

0

trate de usar

IENumerable<MachineRevision> results = from r in entities.MachineRevision 
... 

lugar.

Creo que es la var que está causando el problema.

+0

que ya había tratado, y el resultado es el mismo :-( –

2

¿Por qué no utilizar FirstOrDefault() en su lugar, y comprobar si no? No puedo ver el beneficio al consultar el conteo y luego tomar el primer elemento.

+0

puedo ver su punto. Sin embargo, si uso FirstOrDefault(), Todavía estoy esa NotSupportedException, porque estoy tratando de ejecutar ese método en un objeto de entidad (eso es lo que devuelve la instrucción Linq), no en un IEnumerable. –

0

Editar:

Leer el mensaje de error. "No se puede crear un valor constante de tipo 'Tipo de cierre'. Solo los tipos primitivos ('como Int32, String y Guid') son compatibles en este contexto."

Una de estas comparaciones es con un tipo que no es int, string o guid. Estoy adivinando la Categoría.

r.Machine.IdMachine == pIdMachine && r.Category == pCategory 

Curiosamente, LinqToSql permitirá esta construcción. No sé por qué LinqToEntities no es compatible con esto.

1

No sabía que se crearían diferentes objetos anónimos dependiendo del resultado de la consulta. Supongo que solo querían que los resultados fueran del tipo IEnumerable

¿Qué le parece usar foreach?

var results = from r in entities.MachineRevision 
       where r.Machine.IdMachine == pIdMachine 
       && r.Category == pCategory 
       select r; 

foreach(var r in results) 
{ 
    yield return new oMachineRevision(r.IdMachineRevision); 
} 
2

En la implementación estándar de LINQ, los operadores de "seleccionar" y "dónde" se asignan a los métodos que devuelven un IEnumerable o IQueryable. Por lo tanto, los métodos linq estándar cuando se usan siempre deben devolver un IEnumerable de su consulta, no un solo objeto.

Pero los métodos linq que son candidatos para los operadores linq no están restringidos a los métodos que devuelven IEnumerables, cualquier método que devuelva algo puede ser elegido.

En caso de que tenga métodos de instancia denominados "Seleccionar" y "Dónde" que devuelven un único objeto o métodos de extensiones que son específicos de su clase y devuelven un único objeto, se usarán en lugar de los linq estándar.

Supongo que el método "Seleccionar" o "Dónde" definido en su clase está haciendo que linq devuelva un único valor en lugar de IEnumerable<T>.

0

Creo que también puede seleccionar el artículo que desea de otra manera más simple mediante el uso de expresiones lambda.

var result = entities.MachineRevision 
       .Where(x => x.Machine.IdMachine == pIdMachine) 
       .Where(y => y.Category == (int)pCategory) 
       .FirstOrDefault(); 

if (result != null) 
{ 
    return new oMachineRevision(result.IdMachineRevision); 
} 

y luego proceder como lo haría normalmente

+1

No funciona, porque ".Where (y => y.Category == (int) pCategory)" produce un error. Debes hacer el molde del Enum antes de la consulta. var iCategory = (int) pCategory; y luego simplemente use iCategory en la consulta misma. – derSteve

1

Esto se aplica a todos los tipos implícitos también. Debo admitir que sigo olvidando esto y así es como me encontré con esta publicación.

si tiene

class ClassA { 
       ... 

       private string value; 

       ... 

       public static implicit operator string(ClassA value) 
       { 
        return value.ToString(); 
       } 

       ... 
} 

, es necesario especificar explicitamente la clase a laCadena para la comparación.

por lo que suelen hacer esto

var myClassAStr = myClassA.ToString(); 

    var x = (from a in entites where a.ValToCompare == myClassAStr select a).first(); 

// do stuff with x 
    ... 
+0

en realidad suelo usar a.ValToCompare.Equals (myClassAstr) –