2011-05-04 12 views
6

Tengo una lista que especifica los ID de varios objetos en mi base de datos. Quiero obtener el conjunto de objetos, todos de una tabla, que tienen esos ID y mantenerlos en ese orden exacto, y quiero que se ejecute como una consulta contra el DB (no consultas 'N').Entity Framework Query - Obtiene objetos en orden específico

Por ejemplo, tengo una lista de ID {5, 3, 6, 9}, y quiero recuperar una lista de objetos del Cliente con esos ID y mantenerlos en orden {Cliente (5, 'Bob'), Cliente (3, 'JimBo'), Cliente (6, 'Joe'), Cliente (9, 'Jack')}.

La cantidad de datos es lo suficientemente pequeña como para no tener que volver a ordenarla después de la consulta DB. Podría hacer todo esto en aproximadamente 15 líneas de código limpio (incluida la reordenación a mano), pero creo que debería haber una consulta LINQ de una o dos líneas en contra de EF que debería hacer esto fácilmente.

Respuesta

3

No creo que todo se pueda hacer en una consulta, pero es fácil hacerlo en dos consultas. Uno en DB y uno en memoria.

primera consulta seleccionará sólo los clientes con ID específicos:

var customers = (from c in context.Customers 
       where itemIds.Contains(c.Id) 
       select c).AsEnumerable(); 

En segundo lugar les ordenará según su lista:

var customers = from id in itemIds 
       join c in customers 
       on id equals c.Id 
       select c; 

var customersList = customers.ToList(); 
+0

Gracias. Resulta que AsEnumerable no es necesario (lo comprobé con SQL Profiler), aunque también pensé que sería. Tengo que decir ... mis sentidos arácnidos hormiguean al usar Join para confiar en mantener el orden ordenado. Me pregunto si esa es una propiedad declarada de la documentación de Join in (si no podría cambiar en alguna versión futura de .NET, como por motivos de rendimiento). – pbarranis

3

Creo que tendrá que realizar su pedido después de obtener los resultados. Probablemente lo abordaría así.

var efQuery = /* your query here */.AsEnumerable(); // force evaluation 
var orderedResult = from id in idList // { 5, 3, 6, 9 } 
        join item in efQuery 
        on id equals item.Id 
        select item; 

La unión en la memoria de la lista de ID con el resultado de la consulta conservará el orden de los ID.

Editar: De Comentario

mi Spidey siente cosquilleo en el uso de Ingreso que confiar en el mantenimiento del orden ordenados. Me pregunto si eso es una propiedad declarada de de la documentación de Join (si no podría cambiar en alguna versión futura de de .NET, como por razones de rendimiento de ).

I que apuntan a http://msdn.microsoft.com/en-us/library/bb534675.aspx, la Remarks sección

Ingreso conserva el orden de los elementos de exterior, y para cada uno de estos elementos, el orden de los elementos coincidentes de las interior.

+0

Gracias.Resulta que AsEnumerable no es necesario (lo comprobé con SQL Profiler), aunque también pensé que sería. Tengo que decir ... mis sentidos arácnidos hormiguean al usar Join para confiar en mantener el orden ordenado. Me pregunto si esa es una propiedad declarada de la documentación de Join in (si no podría cambiar en alguna versión futura de .NET, como por motivos de rendimiento). – pbarranis

+0

@pbarranis, descansa fácil. Actualicé la respuesta para abordar la documentación de pedido. –

0

Obviamente puede obtener una lista de objetos donde la lista de ID contiene la ID que se busca con la suficiente facilidad. En cuanto al orden, no hay forma de que pueda hacer esto basado en una lista de ID en una sola consulta. Sin embargo, si usted tiene una forma lógica de especificar cómo se ordenaron las identificaciones originales (si no al azar) a continuación, puede crear una función de la igualdad comparador como se muestra here

-1
void Main() 
{ 
    List<Data> data = new List<Data>(); 
    data.Add(new Data{Id =1, Name = "ABC1"}); 
    data.Add(new Data{Id =2, Name = "ABC2"}); 
    data.Add(new Data{Id =3, Name = "ABC3"}); 
    data.Add(new Data{Id =4, Name = "ABC4"}); 
    data.Add(new Data{Id =5, Name = "ABC5"}); 

    var result = from d in data 
       let ids = new List<int>{3,4,5} 
       where ids.Any(i=> i == d.Id) 
       select d; 
    result.Dump();    
} 

// Define other methods and classes here 
class Data 
{ 
    public int Id{get;set;} 
    public string Name{get;set;} 
} 

Los id podría ser otra consulta para obtener los ID de otro lado, pero ordénelos como desee. Tenga en cuenta que este es un código de Linqpad, por lo tanto, el método .Dump().

+0

-1. No se trata de ordenar y no cumple con EF. – Euphoric

+0

No estoy seguro de por qué lo diría, puede obtener los ID con el orden que desee e inscribirse en él para que los clientes reciban el mismo pedido. Será una consulta. El código adicional allí es para probar. –

Cuestiones relacionadas