2012-02-12 10 views
12

Quiero crear un nuevo objeto de modelo denominado Movie_Type en mi aplicación web ASP.NET MVC. ¿Cuáles serán las diferencias si defino la propiedad de navegación de esta clase como List, ICollection o IQueryable de la siguiente manera?Lista frente a IEnumerable frente a IQueryable al definir la propiedad de navegación

public partial class Movie_Type 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public List<Movie> Movies { get; set; } 
} 

O

public partial class Movie_Type 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public IQueryable<Movie> Movies { get; set; } 
} 

O

public partial class Movie_Type 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public ICollection<Movie> Movies { get; set; } 
} 

Editar: - @Tomas Petricek. gracias por su respuesta. en mi caso estoy usando el primer enfoque de la base de datos y luego uso la plantilla DbContext para mapear mis tablas, lo que automáticamente creó ICollection para todas las propiedades de navegación, entonces mis preguntas son: - 1. ¿Esto significa que no siempre es el mejor elección para usar Icollection. Y debería cambiar las clases generadas automáticamente para que se ajusten mejor a mi caso. 2. En segundo lugar i puede manejar para elegir entre la carga diferida o Eager definiendo .include como

var courses = db.Courses.Include(c => c.Department); 

Independientemente de lo estoy usando para definir las propiedades de navegación. Entonces no puedo entender tu punto. 3. Nunca encontré ejemplos o tutoriales que usen IQuerable para definir las propiedades de navegación, ¿cuál podría ser el motivo? BR

+0

¿Has probado esto antes de publicar aquí? – BrokenGlass

+1

http://stackoverflow.com/questions/3603545/ienumerablet-vs-ilistt-vs-iqueryablet esta publicación lo ayudará a decidir – Devjosh

Respuesta

8

Hay dos posibles formas de ver las cosas:

  1. es el resultado almacenado en la memoria como parte de la instancia del objeto?
    Si elige ICollection, el resultado se almacenará en la memoria; puede que esto no sea una buena idea si el conjunto de datos es muy grande o si no siempre es necesario obtener los datos. Por otro lado, cuando almacene los datos en la memoria, podrá modificar el conjunto de datos de su programa.

  2. ¿Puede refinar la consulta que se envía al servidor SQL?
    Esto significa que podría usar LINQ sobre la propiedad devuelta y los operadores LINQ adicionales se traducirían a SQL. Si no elige esta opción, se ejecutará un procesamiento LINQ adicional en la memoria.

Si desea almacenar datos en la memoria, puede usar ICollection. Si desea poder refinar la consulta, entonces necesita usar IQueryable. Aquí hay una tabla de resumen:

|     | Refine query | Don't change query | 
|-----------------|--------------|--------------------| 
| In-memory  | N/A  | ICollection  | 
| Lazy execution | IQueryable | IEnumerable  | 
+2

+1 - es increíble cómo una imagen (si eso es lo que puede llamar su gráfico) vale la pena 1000 palabras. Acabo de encender una bombilla en el evento :) – Jesse

+0

gracias por tu respuesta, mira mi edición. BR –

+4

No puede usar 'IQueryable ' para una propiedad de navegación. – Slauma

0

Más de un estándar es IEnumerable, ya que es el denominador menos común.

Iqueryable puede devolverse si desea la funcionalidad de consulta adicional para la persona que llama sin tener 10 métodos de depósito para manejar diversos escenarios de consulta.

Un inconveniente es que ienumerable podría 'contar()' lentamente, pero si el objeto implementa ICollection, primero se comprueba esta interfaz para este valor sin tener que enumerar todos los elementos.

También tenga en cuenta si regresa IQueryable a una persona que llama no es de confianza que pueden hacer algunos de fundición y el método pide a la IQueryable y obtener acceso al contexto, la conexión, la cadena de conexión, ejecutar consultas, etc.

También tenga en cuenta nhibernate de ejemplo tiene un objeto de consulta que puede pasar a un repositorio para especificar opciones. Con el marco de entidades, debe devolver IQueryable para mejorar los criterios de consulta

+0

gracias por su respuesta, vea mi edición. BR –

14

No puede usar una propiedad de navegación del tipo IQueryable<T>. Debe usar ICollection<T> o algún tipo de colección que implemente ICollection<T>, como List<T>. (IQueryable<T> no implementa ICollection<T>.)

La propiedad de navegación es simplemente un objeto o una colección de objetos en memoria o es null o la colección está vacía.

Nunca se carga desde la base de datos cuando carga el objeto primario que contiene la propiedad de navegación de la base de datos.

que o bien tienen que decir explícitamente que desea cargar la propiedad de navegación junto con la matriz que sea carga ansiosa:

var movieTypes = context.Movie_Types.Include(m => m.Movies).ToList(); 
// no option to filter or sort the movies collection here. 
// It will always load the full collection into memory 

o será cargada por carga diferida (que está habilitado de forma predeterminada si su propiedad de navegación es virtual):

var movieTypes = context.Movie_Types.ToList(); 
foreach (var mt in movieTypes) 
{ 
    // one new database query as soon as you access properties of mt.Movies 
    foreach (var m in mt.Movies) 
    { 
     Console.WriteLine(m.Title); 
    } 
} 

La última opción es carga explícita que más se aproxime a su intención supongo:

var movieTypes = context.Movie_Types.ToList(); 
foreach (var mt in movieTypes) 
{ 
    IQueryable<Movie> mq = context.Entry(mt).Collection(m => m.Movies).Query(); 
    // You can use this IQueryable now to apply more filters 
    // to the collection or sorting, for example: 
    mq.Where(m => m.Title.StartWith("A")) // filter by title 
     .OrderBy(m => m.PublishDate)   // sort by date 
     .Take(10)        // take only the first ten of result 
     .Load();        // populate now the nav. property 
    // again this was a database query 

    foreach (var m in mt.Movies) // contains only the filtered movies now 
    { 
     Console.WriteLine(m.Title); 
    } 
} 
+2

, lo cual es una pena, porque significa que debe pasar el contexto por todos lados, solo para realizar subconsultas eficaces en lugar de navegación ingenua. – Spongman

0

La colección que marco de la entidad crea para ti si utiliza las propiedades de navegación virtuales implementa ICollection, pero no IQueryable, por lo que no se puede utilizar IQueryable para sus propiedades de navegación, como Slauma dice.

Puede definir sus propiedades como IEnumerable, ya que ICollection extiende IEnumerable, pero si lo hace, perderá la posibilidad de agregar elementos secundarios nuevos a estas propiedades de navegación.

Cuestiones relacionadas