ACTUALIZACIÓN: He recibido algunos votos positivos sobre esto últimamente, así que pensé que le haría saber a la gente que el consejo que doy a continuación no es el mejor. Desde que originalmente comencé a burlarme de hacer Entity Framework en bases de datos antiguas sin clave, me he dado cuenta de que lo mejor que puedes hacer POR MUCHO es hacerlo primero con el código inverso. Hay algunos buenos artículos sobre cómo hacer esto. Simplemente sígalos y luego, cuando desee agregarle una clave, use anotaciones de datos para "falsificar" la clave.
Por ejemplo, supongamos que conozco mi tabla Orders
, aunque no tiene una clave principal, se garantiza que solo tenga un número de pedido por cliente. Como esas son las dos primeras columnas de la tabla, configuraría las primeras clases de código para que se vean así:
[Key, Column(Order = 0)]
public Int32? OrderNumber { get; set; }
[Key, Column(Order = 1)]
public String Customer { get; set; }
Al hacer esto, básicamente estás fingiendo que EF cree que hay una clave agrupada compuesta por OrderNumber y Customer. Esto le permitirá hacer inserciones, actualizaciones, etc. en su tabla sin llave.
Si no está muy familiarizado con hacer primero el Código inverso, vaya y encuentre un buen tutorial sobre el Código de Entity Framework Primero. Luego, busque uno en Reverse Code First (que está haciendo Code First con una base de datos existente). Luego, vuelve aquí y mira mi consejo clave nuevamente. :)
Respuesta original :
Primero: como otros han dicho, la mejor opción es agregar una clave primaria a la tabla. Punto final. Si puedes hacer esto, no sigas leyendo.
Pero si no puede, o simplemente se odia a sí mismo, hay una manera de hacerlo sin la clave principal.
En mi caso, estaba trabajando con un sistema heredado (originalmente archivos planos en un AS400 portado a Access y luego portado a T-SQL). Así que tuve que encontrar un camino. Esta es mi solución Lo siguiente funcionó para mí usando Entity Framework 6.0 (lo último en NuGet a partir de este escrito).
Haga clic derecho en su archivo .edmx en el Explorador de soluciones. Elija "Abrir con ..." y luego seleccione "Editor XML (Texto)". Vamos a editar a mano el código generado automáticamente aquí.
Busque una línea como esta:
<EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" store:Schema="dbo" store:Name="table_nane">
Retirar store:Name="table_name"
del final.
Cambiar store:Schema="whatever"
aSchema="whatever"
Mire debajo de esa línea y encuentre la <DefiningQuery>
etiqueta. Tendrá una gran declaración de selección. Retire la etiqueta y su contenido.
Ahora su línea debería verse así:
<EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />
Tenemos algo más que cambiar. Revisa tu archivo y encuentra esto:
<EntityType Name="table_name">
Cerca de allí probablemente verá algún texto comentado que le advierte que no tenía una clave principal identificada, por lo que la clave se ha inferido y la definición es una tabla / vista de solo lectura. Puedes dejarlo o eliminarlo. Lo borré.
Debajo está la <Key>
etiqueta. Esto es lo que Entity Framework va a utilizar para insertar / actualizar / eliminar. ASÍ QUE ASEGÚRESE DE HACER ESTO CORRECTAMENTE. La propiedad (o propiedades) en esa etiqueta debe indicar una fila identificable de forma única. Por ejemplo, supongamos que conozco mi tabla orders
, aunque no tiene una clave principal, se garantiza que solo tenga un número de pedido por cliente.
Entonces el mío se ve así:
<EntityType Name="table_name">
<Key>
<PropertyRef Name="order_numbers" />
<PropertyRef Name="customer_name" />
</Key>
En serio, no hagas esto mal. Digamos que, aunque nunca debería haber duplicados, de alguna manera dos filas ingresan a mi sistema con el mismo número de pedido y nombre de cliente. Whooops! ¡Eso es lo que obtengo por no usar una llave! Entonces uso Entity Framework para eliminar uno. Como sé que el duplicado es el único pedido realizado hoy, hago esto:
var duplicateOrder = myModel.orders.First(x => x.order_date == DateTime.Today);
myModel.orders.Remove(duplicateOrder);
¿Adivina qué? ¡Acabo de eliminar tanto el duplicado como el original! Eso es porque le dije a Entity Framework que order_number / cutomer_name era mi clave principal. Entonces, cuando le dije que eliminara el pedido duplicado, lo que hizo en segundo plano fue algo como:
DELETE FROM orders
WHERE order_number = (duplicateOrder's order number)
AND customer_name = (duplicateOrder's customer name)
Y con esa advertencia ... ¡ahora deberías estar listo!