Pregunta

Tengo una consulta LINQ asignada con Entity Framework que se parece a esto:

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

Esto devuelve un objeto de imagen única y funciona según lo previsto.

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

Básicamente, en su estado actual mi consulta linq está haciendo:

Select ImageId, Name, Data
From Images
...

Pero necesito una consulta que haga esto en su lugar:

Select ImageId, Name
From Images
...

Observe que quiero cargar todo excepto los datos.(Puedo obtener estos datos en una segunda pasada asíncrona)

¿Fue útil?

Solución

Por desgracia, si se utiliza LINQ a SQL, no existe una solución óptima.

Usted tiene 3 opciones:

  1. Se vuelve a 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 elige sus campos y devolver una clase personalizada inflexible, pero se pierde el seguimiento, si eso es lo que quieren.

I love LINQ a SQL, pero esa es la manera que es.

Mi única solución para usted sería para reestructurar su base de datos y mover todos los grandes de datos en una tabla separada, y enlazar con él desde la tabla de imagen.

De esta manera al regresar imagen tan solo te devuelve una clave en el nuevo campo ID de datos, y luego se podría acceder a esos datos más pesado cuando y si lo necesitas.

aplausos

Otros consejos

Esto creará una nueva imagen con sólo los campos establecidos. Cuando vuelva a obtener los datos de las imágenes que seleccione, sugeriría seguir adelante y obtener el conjunto de datos completo en lugar de tratar de combinarlo con los datos de nombre / ID existentes. Los campos de nombre / ID son presumiblemente pequeño 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 para realmente construir un objeto de imagen, usando un tipo anónimo podrían satisfacer sus propósitos igual de bien.

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();

[Si usa Linq 2 SQL] Dentro del diseñador DBML, hay una opción para hacer que las columnas de la tabla individuales se carguen con retraso.Establezca esto en verdadero para su campo binario grande.Luego, esos datos no se cargan hasta que realmente se utilizan.

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

Solución n.° 2 (para marco de entidad o linq 2 sql):

Cree una vista de la tabla que incluya solo la clave principal y varchar(max)/varbinary(max).Mapee eso en 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 en esa tabla, aunque puede verificarlo con el registrador.

Generalmente, 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.Es posible que pueda escribir en la vista, o que necesite escribir un procedimiento almacenado, o puede generar un archivo DBML para una tabla.

No se puede hacer con LINQ al menos por ahora ...

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

Como alternativa puede usar 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 general, porque me resulta más legible y comprensible.

Gracias :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top