2009-05-30 13 views
9

Tengo una consulta LINQ mapeada con el marco de la entidad que se ve algo como esto:LINQ - ¿NO selecciona ciertos campos?

image = this.Context.ImageSet 
        .Where(n => n.ImageId == imageId) 
        .Where(n => n.Albums.IsPublic == true) 
        .Single(); 

Esto devuelve un único objeto de imagen y funciona como está previsto.

Sin embargo, esta consulta devuelve todas las propiedades de mi tabla de imágenes en la base de datos. En circunstancias normales, esto estaría bien, pero estas imágenes contienen una gran cantidad de datos binarios que tarda mucho tiempo en regresar.

Básicamente, en el que el estado actual de mi consulta LINQ está haciendo:

Select ImageId, Name, Data 
From Images 
... 

pero necesito una consulta que hace esto instread:

Select ImageId, Name 
From Images 
... 

Aviso quiero cargar todo, excepto el de datos. (Puedo obtener estos datos en un segundo pase asíncrono)

Respuesta

8

Desafortunadamente, si usa LINQ to SQL, no hay una solución óptima.

usted tiene 3 opciones:

  1. que regrese la Entidad, con seguimiento Contexto y todo, en este caso de la imagen, con todos los campos
  2. usted elige sus campos y devolver un tipo anónimo
  3. Usted elije tus campos y devuelve una clase personalizada fuertemente tipada, pero pierdes el seguimiento, si eso es lo que quieres.

Me encanta LINQ to SQL, pero así son las cosas.

Mi única solución para usted sería reestructurar su base de datos, mover todos los datos grandes en una tabla separada y vincularla desde la tabla de imágenes.

De esta manera, al devolver la imagen, solo devolvería una clave en el nuevo campo ID de datos, y luego podría acceder a los datos más pesados ​​cuando y si los necesita.

aplausos

+0

Creo que sin la opción de demora de carga como LINQ to SQL, esta es la mejor solución para mí. – vidalsasoon

+0

Sí, creo que con LINQ to SQL a veces tienes que cambiar tu esquema para que se ajuste al modelo. a veces descubren que realmente termina haciendo que su diseño de base de datos sea mejor ....? – andy

1

Esto creará una nueva imagen con solo esos campos establecidos. Cuando vuelva a obtener los datos para las imágenes que seleccione, le sugiero que siga adelante y obtenga el conjunto de datos completo en lugar de tratar de fusionarlo con los datos de id/name existentes. Los campos id/name son presumiblemente pequeños en relación con los datos y el código será mucho más simple que tratar de hacer la fusión. Además, puede que no sea necesario construir realmente un objeto de imagen, utilizando un tipo anónimo que también se adapte a sus propósitos.

image = this.Context.ImageSet 
        .Where(n => n.ImageId == imageId) 
        .Where(n => n.Albums.IsPublic == true) 
        .Select(n => new Image { ImageId = n.ImageId, Name = n.Name } 
        .Single(); 
+1

Pensé en la solución que me proporcionó, pero mi preocupación fue perder el estado de la entidad ya que se está creando una nueva imagen. Además, el tipo de devolución es "Imagen", por lo que no creo que sea posible el tipo Anónimo. Voy a hacer algunas pruebas thx – vidalsasoon

0

otra posibilidad es utilizar el selecto nuevo en la expresión de consulta ...

var image = 
(
    from i in db.ImageSet 
    where i.ImageId == imageId && i.Albums.IsPublic 
    select new 
    { 
     ImageId = i.ImageId, 
     Name = i.Name 
    } 
).Single() 

Las expresiones de consulta LINQ en realidad se convierten a la expresión Lambda en tiempo de compilación, pero prefair usando la expresión de consulta en general porque me resulta más legible y comprensible.

Gracias :)

1

[Si el uso de Linq 2 SQL] Dentro del diseñador DBML, hay una opción para hacer columnas en el cuadro individual retrasan-cargado. Establezca esto en verdadero para su gran campo binario. Entonces, esos datos no se cargan hasta que realmente se usen.

[Pregunta para todos ustedes: ¿Alguien sabe si los marcos de entidades soportan varbinary/varchar's con carga diferida en MSVS 2010? ]

Solución # 2 (para el marco de la entidad o linq sql 2): ​​

crear una vista de la tabla que incluye sólo la clave principal y la varchar (max)/varbinary (max). Asigna eso a EF.

Dentro de su diseñador de Entity Framework, elimine la propiedad varbinary (max)/varchar (max) de la definición de la tabla (dejándola definida solo en la vista). Esto debería excluir el campo de las operaciones de lectura/escritura de esa tabla, aunque puede verificarlo con el registrador.

En general, accederá a los datos a través de la tabla que excluye el blob de datos. Cuando necesita el blob, carga una fila desde la vista. No estoy seguro de si podrá escribir en la vista, no estoy seguro de cómo escribiría. Puede escribir en la vista, o puede necesitar escribir un procedimiento almacenado, o puede extraer un archivo DBML para la tabla.

+0

Creo que esto es solo para LINQ to SQL? Demasiado. habría sido perfecto – vidalsasoon

+0

Vaya, sí, esto puede ser linq 2 sql solamente. –

+0

[Pregunta para todos ustedes: ¿Alguien sabe si los marcos de entidad soportan varbinary/varchar's cargados retrasados ​​en MSVS 2010? ] RESPUESTA: NO :( – vidalsasoon

1

No puede hacerlo con LINQ al menos por ahora ...

El mejor enfoque que sé es crear View para la tabla que necesita sin grandes campos y utilizar LINQ con que View.

+1

sí, es solo la manera! Intenté seleccionar algunos campos con clase personalizada, pero el problema sigue siendo un campo nvarchar (max) con xmlFile no está dentro, no en el seleccione pero bloquee con Error al ejecutar la solicitud secundaria para el controlador 'System.Web.Mvc.HttpHandlerUtil + ServerExecuteHttpHandlerAsyncWrapper'. Utilicé la vista sin archivos grandes y funciona. – Evilripper

Cuestiones relacionadas