2012-07-17 11 views
11

Tenemos un cliente muy grande mesa con más de columnas (sé que alguien hace eso!)Seleccionar columnas específicas de la base de datos utilizando código de EF Primera

Muchas de estas columnas son de hecho claves externas a otras tablas.

También tenemos el requisito de carga ansiosa algunas de las tablas relacionadas.

¿Hay alguna forma en Linq a SQL o Dynamic Linq para especificar qué columnas se recuperarán de la base de datos? Busco a una declaración de LINQ que en realidad tiene este efecto en la instrucción SQL generada:

SELECT Id, Name FROM Book 

Cuando ejecutamos la consulta reguar generada por EF, SQL Server genera un error que ha alcanzado el número máximo de columnas que se puede seleccionar dentro de una consulta !!!

¡Cualquier ayuda es muy apreciada!


Sí exactamente este es el caso, la tabla tiene 500 columnas y es autorreferenciado nuestra herramienta de carga automáticamente ansiosos las primeras relaciones de nivel y esto golpea el límite de SQL en el número de columnas que se pueden consultar.

Tenía la esperanza de que pueda fijar a solamente carga columnas limitadas de las entidades relacionadas, tales como identificador y el nombre (que se utiliza en la interfaz de usuario para ver el registro de usuario)

supongo que la otra opción es controlar qué columnas FK deberían estar ansiosas cargadas. Sin embargo, esto sigue siendo un problema para las tablas que tienen una columna binaria o ntext, que es posible que no desee cargar todas las veces.

¿Hay alguna manera de enlazar varios modelos (Entidades) a la misma tabla en Code First? Intentamos hacer esto, creo que el esfuerzo falló miserablemente.

Respuesta

18

sí se puede devolver sólo subconjunto de columnas mediante el uso de proyección:

var result = from x in context.LargeTable 
      select new { x.Id, x.Name }; 

El problema: la proyección y con ganas de carga no trabaja en conjunto. Una vez que empiezas a usar proyecciones o combinaciones personalizadas, estás cambiando la forma de la consulta y no puedes usar Include (EF lo ignorará). La única manera de tal escenario es incluir manualmente las relaciones en el conjunto de resultados proyectado:

var result = from x in context.LargeTable 
      select new { 
       Id = x.Id, 
       Name = x.Name, 
       // You can filter or project relations as well 
       RelatedEnitites = x.SomeRelation.Where(...) 
      }; 

También puede proyectar el tipo específico, pero ese tipo específico no debe ser asignada (por lo que no puede, por ejemplo proyecto para LargeTable entidad de mi muestra). La proyección a la entidad mapeada se puede hacer solo en datos materializados en Linq-to-objects.

Editar:

Es probable que haya algún malentendido cómo funciona EF. EF funciona sobre entidades: la entidad es lo que ha mapeado. Si mapea 500 columnas a la entidad, EF simplemente usa esa entidad como la definió. Significa que las consultas cargan la entidad y la entidad que guarda persiste.

¿Por qué funciona de esta manera? La entidad se considera como una estructura de datos atómicos y sus datos pueden cargarse y rastrearse solo una vez; esa es una característica clave para poder persistir correctamente los cambios a la base de datos.Esto no significa que no deba cargar solo un subconjunto de columnas si lo necesita, pero debe comprender que la carga del subconjunto de columnas no define su entidad original; se considera una vista arbitraria de los datos en su entidad. Esta vista no se rastrea y no se puede recuperar en la base de datos sin un esfuerzo adicional (simplemente porque EF no contiene ninguna información sobre el origen de la proyección).

EF también poner algunas restricciones adicionales sobre la capacidad de mapear la entidad

  • Cada tabla puede ser normalmente enlazada sólo una vez. ¿Por qué? De nuevo porque la tabla de asignación varias veces a diferentes entidades puede interrumpir la capacidad para persistir correctamente esas entidades; por ejemplo, si una columna que no es clave se asigna dos veces y carga una instancia de ambas entidades asignadas al mismo registro, ¿cuál de los valores asignados usará durante ¿guardando cambios?
  • hay dos excepciones que permiten la tabla de asignaciones varias veces
    • tabla por jerarquía de herencia - esta es una asignación en la tabla puede contener registros de múltiples tipos de entidades definidas en jerarquía de herencia. Las columnas asignadas a la entidad base en la jerarquía deben ser compartidas por todas las entidades. Cada tipo de entidad derivada puede tener sus propias columnas asignadas a sus propiedades específicas (otros tipos de entidades tienen estas columnas siempre vacías). No es posible compartir columnas para propiedades derivadas entre múltiples entidades. También debe haber una columna adicional llamada diciendo discriminador EF, que tipo de entidad se almacena en el registro - este columnas no pueden asignarse como propiedad debido a que ya está asignada como tipo discriminador.
    • División de tabla: esta es una solución directa para la limitación de asignación de tabla única. Le permite dividir la tabla en varias entidades con algunas restricciones:
      • Debe haber una relación de uno a uno entre las entidades. Usted tiene una entidad central utilizada para cargar los datos básicos y todas las demás entidades son accesibles a través de las propiedades de navegación de esta entidad. La carga ansiosa, la carga lenta y la carga explícita funcionan normalmente.
      • La relación es real 1-1 por lo que ambas partes o relación debe siempre existe.
      • Las entidades no deben compartir cualquier propiedad excepto la tecla - esta restricción va a resolver el problema inicial, porque cada propiedad modificable está asignada una sola vez
      • Cada entidad de la tabla de división debe tener una propiedad clave asignada
      • inserción requiere objeto entero gráfico a ser poblada porque otras entidades pueden contener asignada columnas necesarias

Linq-to-SQL también contiene posibilidad de marcar una columna como perezoso cargado pero thi s función todavía no está disponible en la FE - se puede vote for that feature.

Conduce a sus opciones para la optimización

  • Use proyecciones para obtener sólo lectura "vista" para la entidad
    • Usted puede hacer eso en la consulta LINQ como he mostrado en la parte anterior de este responder
    • puede crear vistas de base de datos y el mapa como una nueva "entidad"
    • en EDMX también puede utilizar Definir consulta o vista de consultas SQL para encapsular ya sea o proyección ESQL en su mapeo
  • Utilice la tabla de división
    • EDMX que permite mesa de división a muchas entidades sin ningún problema
    • Code first allows you splitting table así, pero hay algunos problemas cuando la tabla de división para más de dos entidades (creo que requiere cada tipo de entidad para tener propiedad de navegación para todos los otros tipos de entidades de la tabla dividida, eso hace que sea realmente difícil de usar).
+0

Tenía la esperanza de que haya una forma más sólida de especificar las columnas. En muchos casos, nuestra aplicación MVC se comparte para varios modelos y estamos utilizando dynamic linq para poder realizar la misma consulta para diferentes tablas. – sam360

+0

Dynamic linq también debería poder especificar la proyección. EF es una herramienta para trabajar con entidades: la entidad es lo que ha mapeado = si ha mapeado 500 columnas a la entidad, su consulta sin proyección siempre devolverá 500 columnas + columnas de todas las relaciones cargadas impacientes. –

+0

Sí, exactamente este es el caso, la tabla tiene 500 columnas y se autoreferencia de manera automática nuestra herramienta carga las relaciones de primer nivel y esto alcanza el límite de SQL en el número de columnas que se pueden consultar. Tenía la esperanza de configurar solo para cargar columnas limitadas de las entidades relacionadas como Id y Name (que se usa en la interfaz de usuario para ver el registro en el usuario) Supongo que la otra opción es controlar qué columnas deberían estar ansioso de cargar. Sin embargo, esto sigue siendo un problema para las tablas que tienen una columna binaria o ntext, por lo que es posible que no desee cargar todas las relaciones – sam360

0

Crear procedimientos almacenados que consultan el número de columnas necesarias y luego llamar a los procedimientos almacenados de código.

Cuestiones relacionadas