2009-04-16 39 views
36

Tengo IQueryable <> objeto.Convertir el objeto tipo IQueryable <> a List <T> type?

Quiero convertirlo en la lista <> con columnas seleccionadas como new { ID = s.ID, Name = s.Name }.

Editado

Marc tiene usted toda la razón!

pero solo tengo acceso al método FindByAll() (debido a mi arquitectura).

Y me da objeto completo en IQueryable <>.

Y tengo un requisito estricto (para crear el objeto json para la etiqueta de selección) tener solo la lista <> escribir con dos campos.

+0

Entonces, ¿qué falla si usa FindByAll (...). Seleccione (s => nuevo {ID = ID., Nombre = s.Name}). ToList()? –

+0

Tenga en cuenta también el comentario en mi respuesta sobre la creación de su propio tipo si es necesario. Json.NET podría exigir propiedades editables, en cuyo caso necesitará su propio tipo (los tipos anónimos de C# son inmutables). –

Respuesta

56

A continuación, sólo Select:

var list = source.Select(s=>new { ID = s.ID, Name = s.Name }).ToList(); 

(edit) En realidad - los nombres podrían ser inferidos en este caso, lo que podría utilizar:

var list = source.Select(s=>new { s.ID, s.Name }).ToList(); 

lo que ahorra un par de electrones ...

+0

Según mi Nivel, solo puedo obtener el objeto completo mediante consulta lineal. ese es el problema – Vikas

+0

¿Puedes explicarlo? No entiendo el comentario. –

+4

Si quiere decir que necesita devolver este objeto entre niveles, deberá crear un tipo regular con una ID y un Nombre, y Seleccionar (s => nuevo YourType {ID = s.ID, Name = s.Name}).Listar(); –

6

System.Linq tiene ToList() en IQueryable <> e IEnumerable <>. Sin embargo, causará un pase completo a través de los datos para ponerlo en una lista. Pierdes tu invocación diferida cuando haces esto. No es gran cosa si es el consumidor de los datos.

33

Añadir utilizando System.Linq y llamar a la ToList() en el IQueryable <>

+0

Me faltaba la directiva de uso, aplausos – pauliephonic

+1

@pauliephonic que debería empezar a utilizar (juego de palabras) ReSharper, entonces nunca tendrá que escribir otra declaración de uso de nuevo ;-) – nashwan

+0

Simple, preciso, hermoso! –

1

Aquí hay un par de métodos de extensión que he improvisado juntos para convertir IQueryables y IEnumerables de un tipo a otro (es decir DTO) Se usa principalmente para convertir de un tipo más grande (es decir, el tipo de la fila en la base de datos que tiene campos innecesarios) a uno más pequeño.

Los aspectos positivos de este enfoque son:

  • prácticamente no requiere código para utilizar - una simple llamada a .Transform <DtoType>() es todo lo que necesita
  • funciona igual que .Elija (s => new {...}) es decir, cuando se usa con IQueryable produce el código SQL óptimo, excluyendo los campos Type1 que DtoType no tiene.

LinqHelper.cs:

public static IQueryable<TResult> Transform<TResult>(this IQueryable source) 
{ 
    var resultType = typeof(TResult); 
    var resultProperties = resultType.GetProperties().Where(p => p.CanWrite); 

    ParameterExpression s = Expression.Parameter(source.ElementType, "s"); 

    var memberBindings = 
     resultProperties.Select(p => 
      Expression.Bind(typeof(TResult).GetMember(p.Name)[0], Expression.Property(s, p.Name))).OfType<MemberBinding>(); 

    Expression memberInit = Expression.MemberInit(
     Expression.New(typeof(TResult)), 
     memberBindings 
     ); 

    var memberInitLambda = Expression.Lambda(memberInit, s); 

    var typeArgs = new[] 
     { 
      source.ElementType, 
      memberInit.Type 
     }; 

    var mc = Expression.Call(typeof(Queryable), "Select", typeArgs, source.Expression, memberInitLambda); 

    var query = source.Provider.CreateQuery<TResult>(mc); 

    return query; 
} 

public static IEnumerable<TResult> Transform<TResult>(this IEnumerable source) 
{ 
    return source.AsQueryable().Transform<TResult>(); 
} 
+0

Para personas que provienen de mundos de Hibernate/NHibernate a Linq: la funcionalidad es aproximadamente la misma que la de NHibernate **. SetResultTransformer (Transformers.AliasToBean (typeof (DtoType))) ** o Hibernate **. SetResultTransformer (Transformers.aliasToBean (DtoType. clase)) ** – Vedran

6

el constructor de la clase List puede convertir IQueryable para usted:

public static List<TResult> ToList<TResult>(this IQueryable source) 
{ 
    return new List<TResult>(source); 
} 

o simplemente puede convertirlo sin el método de extensión, por supuesto:

var list = new List<T>(queryable); 
+0

¡Eso fue maravilloso .....! Gracias. –

+0

Su bienvenida. Realmente me pregunto por qué esta extensión no se incluyó en .NET para comenzar ... – mmmeff

+0

Disculpa, no te entendí. ¿Qué quiere decir con "por qué esta extensión no se incluyó ..."? Sin embargo, está funcionando. –

Cuestiones relacionadas