Por varias razones de las que no tengo libertad para hablar, estamos definiendo una vista en nuestra base de datos Sql Server 2005 de la siguiente manera:
CREATE VIEW [dbo].[MeterProvingStatisticsPoint]
AS
SELECT
CAST(0 AS BIGINT) AS 'RowNumber',
CAST(0 AS BIGINT) AS 'ProverTicketId',
CAST(0 AS INT) AS 'ReportNumber',
GETDATE() AS 'CompletedDateTime',
CAST(1.1 AS float) AS 'MeterFactor',
CAST(1.1 AS float) AS 'Density',
CAST(1.1 AS float) AS 'FlowRate',
CAST(1.1 AS float) AS 'Average',
CAST(1.1 AS float) AS 'StandardDeviation',
CAST(1.1 AS float) AS 'MeanPlus2XStandardDeviation',
CAST(1.1 AS float) AS 'MeanMinus2XStandardDeviation'
WHERE 0 = 1
La idea es que Entity Framework creará una entidad basada en esta consulta, lo que hace, pero la genera con un error que establece lo siguiente:
Advertencia 6002: La tabla / vista 'Keystone_Local.dbo.MeterProvingStatisticsPoint' no tiene una clave principal definida. Se ha inferido la clave y la definición se creó como una tabla / vista de solo lectura.
Y decide que el campo CompletedDateTime será la clave principal de esta entidad.
Estamos usando EdmGen para generar el modelo. ¿Hay alguna manera de que el marco de la entidad no incluya ningún campo de esta vista como clave principal?
fuente
Pude resolver esto usando el diseñador.
No tuve que cambiar mi punto de vista para usar las soluciones ISNULL, NULLIF o COALESCE. Si actualiza su modelo desde la base de datos, las advertencias volverán a aparecer, pero desaparecerán si cierra y vuelve a abrir VS. Los cambios que realizó en el diseñador se conservarán y no se verán afectados por la actualización.
fuente
De acuerdo con @Tillito, sin embargo, en la mayoría de los casos dañará el optimizador de SQL y no usará los índices correctos.
Puede ser obvio para alguien, pero pasé horas resolviendo problemas de rendimiento con la solución Tillito. Digamos que tienes la mesa:
y tu punto de vista es algo como esto
El optimizador SQL no usará index ix_customer y realizará un escaneo de tabla en el índice primario, pero si en lugar de:
tu usas
hará que MS SQL (al menos 2008) incluya el índice correcto en el plan.
Si
fuente
Este método me funciona bien. Uso ISNULL () para el campo de clave principal y COALESCE () si el campo no debe ser la clave principal, sino que también debe tener un valor no anulable. Este ejemplo produce un campo ID con una clave primaria no anulable. Los otros campos no son claves y tienen (Ninguno) como su atributo Anulable.
si realmente no tiene una clave principal, puede suplantarla utilizando ROW_NUMBER para generar una pseudoclave que su código ignora. Por ejemplo:
fuente
NEWID() as id
, pero es la misma idea. Y hay casos de uso legítimos, por ejemplo, si tiene una vista de solo lectura. Feo, EF, feo.El generador de EDM de Entity Framework actual creará una clave compuesta a partir de todos los campos no anulables en su vista. Para obtener el control sobre esto, deberá modificar la vista y las columnas de la tabla subyacente configurando las columnas como anulables cuando no desee que formen parte de la clave principal. Lo contrario también es cierto, como encontré, la clave generada por EDM estaba causando problemas de duplicación de datos, por lo que tuve que definir una columna anulable como no anulable para forzar que la clave compuesta en el EDM incluya esa columna.
fuente
Context.Entity.ToList()
registros duplicados, pero si ejecuta la consulta SQL generada por EF directamente (obtenida con LINQPad), no se produce la duplicación de registros. Parece ser un problema al asignar los registros de la base de datos a los objetos de entidad (POCO) devueltos, ya que la PK se infiere usando la lógica explicada (columnas no anulables).Parece que es un problema conocido con EdmGen: http://social.msdn.microsoft.com/forums/en-US/adodotnetentityframework/thread/12aaac4d-2be8-44f3-9448-d7c659585945/
fuente
Para obtener una vista, solo tenía que mostrar una columna de clave principal. Creé una segunda vista que apuntaba a la primera y usé NULLIF para hacer que los tipos fueran anulables. Esto me funcionó para hacer que el EF pensara que solo había una clave principal en la vista.
Sin embargo, no estoy seguro de si esto lo ayudará, ya que no creo que el EF acepte una entidad sin clave primaria.
fuente
Si no desea meterse con lo que debería ser la clave principal, le recomiendo:
ROW_NUMBER
a su selecciónfuente
Debido a los problemas mencionados anteriormente, prefiero las funciones de valor de tabla.
Si tienes esto:
crea esto:
Luego simplemente importa la función en lugar de la vista.
fuente