sintaxis query inner framework consultas c# linq-to-sql entity

c# - inner - DefintingQuery y ningún elemento<DeleteFunction> existe en el elemento<ModificationFunctionMapping> para admitir la operación actual



linq notation c# (3)

No se puede actualizar EntitySet ''InstanceObjectName'' porque tiene DefiningQuery y no existe ningún elemento en el elemento para admitir la operación actual


Entity Framework no sabe si una vista determinada es actualizable o no, por lo que agrega el elemento para evitar que el marco intente generar consultas en una vista no actualizable.

Si su vista es actualizable, puede simplemente eliminar el elemento de la definición de EntitySet para su vista dentro de la sección StorageModel de su .edmx, y el proceso de actualización normal funcionará como con cualquier otra tabla.

Si su vista no es actualizable, deberá proporcionar la lógica de actualización usted mismo a través de un "Mapeo de función de modificación". El mapeo de funciones de modificación llama a una función definida en la sección StorageModel de su .edmx. Esa función puede contener el nombre y los argumentos de un procedimiento almacenado en su base de datos, o puede usar un "comando de definición" para escribir la instrucción de inserción, actualización o eliminación directamente en la definición de función dentro de la sección StorageModel de su .edmx .

De las dos opciones, si su vista es actualizable (lo que parece que puede ser), lo más fácil es eliminar el insertado por el diseñador.


¡Asegúrate de que tu tabla tenga una clave principal!


ACTUALIZACIÓN: He recibido algunos votos al respecto últimamente, así que pensé que le haría saber a la gente que los consejos que doy a continuación no son los mejores. Desde que originalmente comencé a utilizar Entity Framework en bases de datos antiguas sin claves, me he dado cuenta de que lo mejor que puedes hacer BY FAR es hacerlo primero con código inverso. Hay algunos buenos artículos sobre cómo hacer esto. Simplemente sígalos, y luego cuando quiera agregarle una clave, use anotaciones de datos para "falsificar" la clave.

Por ejemplo, supongamos que sé que mis Orders mesa, si bien no tienen una clave principal, solo tienen un número de pedido por cliente. Como esas son las dos primeras columnas de la tabla, configuré 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 ha fingido que EF cree que hay una clave en clúster compuesta por OrderNumber y Customer. Esto le permitirá hacer inserciones, actualizaciones, etc. en su tabla sin llave.

Si no está muy familiarizado con hacer el cambio de código primero, busque primero un buen tutorial sobre Entity Framework Code. Luego, una vez que se sienta cómodo con esto, busque uno en Código inverso primero (que está haciendo Code First con una base de datos existente). Entonces vuelve aquí y mira mi consejo clave de nuevo. :)

Respuesta Original :

Primero: como otros han dicho, la mejor opción es agregar una clave principal a la tabla. Punto final. Si puedes hacer esto, no sigas leyendo.

Pero si no puedes, o simplemente te odias a ti mismo, hay una manera de hacerlo sin la clave principal. Básicamente, lo que vamos a hacer es mentir al Entity Framework y decirle que hay una clave principal.

En mi caso, estaba trabajando con un sistema heredado (originalmente archivos planos en un AS400 portado a Access y luego transferido a T-SQL). Entonces tuve que encontrar un camino. Esta es mi solución. Lo siguiente funcionó para mí al usar Entity Framework 6.0 (el último en NuGet al momento de escribir esto).

  1. Haga clic derecho en su archivo .edmx en el Explorador de soluciones. Elija "Abrir con ..." y luego seleccione "XML (Text) Editor". Aquí vamos a editar manualmente el código generado automáticamente.

  2. 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">

  3. Eliminar store:Name="table_name" desde el final.

  4. Cambiar store:Schema="whatever" a Schema="whatever"

  5. Mire debajo de esa línea y encuentre la etiqueta <DefiningQuery> . Tendrá una gran declaración selecta en él. Elimina la etiqueta y su contenido.

  6. Ahora tu línea debería verse más o menos así:
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />

  7. Tenemos algo más que cambiar. Revise su archivo y encuentre esto:
    <EntityType Name="table_name">

  8. Cerca de allí, probablemente verá algún texto comentado advirtiéndole 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é.

  9. A continuación está la etiqueta <Key> . Esto es lo que Entity Framework va a utilizar para insertar / actualizar / eliminar. ASÍ QUE ASEGÚRESE DE HACER ESTE DERECHO. La propiedad (o propiedades) en esa etiqueta necesita indicar una fila identificable de manera única. Por ejemplo, digamos que sé que mis orders mesa, si bien no tienen una clave principal, solo tienen 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 debe haber duplicados, de alguna manera dos filas ingresan a mi sistema con el mismo número de orden y nombre de cliente. ¡Whooops! ¡Eso es lo que obtengo por no usar una llave! Entonces utilizo Entity Framework para eliminar uno. Como sé que el duplicado es el único pedido presentado 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 duplicateOrder, lo que hizo en el fondo fue algo así 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!