Cuando guardo una entidad con el marco de la entidad, naturalmente asumí que solo intentaría guardar la entidad especificada. Sin embargo, también está intentando salvar las entidades secundarias de esa entidad. Esto está provocando todo tipo de problemas de integridad. ¿Cómo fuerzo a EF a guardar solo la entidad que quiero guardar y, por lo tanto, ignorar todos los objetos secundarios?
Si configuro manualmente las propiedades en nulo, aparece un error "La operación falló: la relación no se pudo cambiar porque una o más de las propiedades de clave externa no aceptan nulos". Esto es extremadamente contraproducente ya que configuré el objeto secundario en nulo específicamente para que EF lo dejara en paz.
¿Por qué no quiero guardar / insertar los objetos secundarios?
Dado que esto se está discutiendo de un lado a otro en los comentarios, daré una justificación de por qué quiero que mis objetos secundarios se dejen tranquilos.
En la aplicación que estoy creando, el modelo de objetos EF no se carga desde la base de datos, sino que se usa como objetos de datos que estoy completando mientras analizo un archivo plano. En el caso de los objetos secundarios, muchos de estos se refieren a tablas de búsqueda que definen varias propiedades de la tabla principal. Por ejemplo, la ubicación geográfica de la entidad principal.
Dado que yo mismo llené estos objetos, EF asume que estos son objetos nuevos y deben insertarse junto con el objeto principal. Sin embargo, estas definiciones ya existen y no quiero crear duplicados en la base de datos. Solo uso el objeto EF para realizar una búsqueda y completar la clave externa en la entidad de mi tabla principal.
Incluso con los objetos secundarios que son datos reales, primero necesito guardar al padre y obtener una clave principal o EF parece hacer un lío de cosas. Espero que esto dé alguna explicación.
fuente
Respuestas:
Hasta donde yo sé, tienes dos opciones.
Opción 1)
Anule todos los objetos secundarios, esto asegurará que EF no agregue nada. Tampoco eliminará nada de su base de datos.
Opcion 2)
Configure los objetos secundarios como separados del contexto usando el siguiente código
Tenga en cuenta que no puede separar un
List
/Collection
. Tendrá que recorrer su lista y separar cada elemento de su lista como talfuente
En pocas palabras: use una clave externa y le salvará el día.
Suponga que tiene una entidad de escuela y una entidad de ciudad , y esta es una relación de muchos a uno en la que una ciudad tiene muchas escuelas y una escuela pertenece a una ciudad. Y suponga que las ciudades ya existen en la tabla de búsqueda, por lo que NO desea que se vuelvan a insertar al insertar una nueva escuela.
Inicialmente, podría definir sus entidades como esta:
Y puede hacer la inserción de la escuela de esta manera (suponga que ya tiene la propiedad de la ciudad asignada al nuevo elemento ):
El enfoque anterior puede funcionar perfectamente en este caso, sin embargo, prefiero el enfoque de clave externa , que para mí es más claro y flexible. Vea la solución actualizada a continuación:
De esta manera, define explícitamente que la escuela tiene una clave externa City_Id y se refiere a la entidad City . Entonces, cuando se trata de la inserción de School , puede hacer:
En este caso, especificas explícitamente el City_Id del nuevo registro y eliminas el City del gráfico para que EF no se moleste en agregarlo al contexto junto con School .
Aunque a la primera impresión el enfoque de clave externa parece más complicado, créame, esta mentalidad le ahorrará mucho tiempo cuando se trata de insertar una relación de varios a varios (imaginando que tiene una relación entre la escuela y el estudiante, y el estudiante tiene una propiedad de la ciudad) y así sucesivamente.
Espero que esto te sea útil.
fuente
[Range(1, int.MaxValue)]
atributo?Si solo desea almacenar cambios en un objeto principal y evitar almacenar cambios en cualquiera de sus objetos secundarios , entonces ¿por qué no hacer lo siguiente?
La primera línea adjunta el objeto principal y todo el gráfico de sus objetos secundarios dependientes al contexto en
Unchanged
estado.La segunda línea cambia el estado del objeto padre únicamente, dejando a sus hijos en el
Unchanged
estado.Tenga en cuenta que utilizo un contexto recién creado, por lo que esto evita guardar otros cambios en la base de datos.
fuente
Una de las soluciones sugeridas es asignar la propiedad de navegación desde el mismo contexto de base de datos. En esta solución, se reemplazaría la propiedad de navegación asignada desde fuera del contexto de la base de datos. Por favor, vea el siguiente ejemplo como ilustración.
Guardando en la base de datos:
Microsoft incluye esto como una característica, sin embargo, me parece molesto. Si el objeto del departamento asociado con el objeto de la empresa tiene una identificación que ya existe en la base de datos, entonces ¿por qué EF no asocia el objeto de la empresa con el objeto de la base de datos? ¿Por qué deberíamos cuidar de la asociación por nosotros mismos? Cuidar la propiedad de navegación durante la adición de un nuevo objeto es algo así como mover las operaciones de la base de datos de SQL a C #, algo engorroso para los desarrolladores.
fuente
Primero debe saber que hay dos formas de actualizar la entidad en EF.
En la aplicación que estoy creando, el modelo de objetos EF no se carga desde la base de datos, sino que se usa como objetos de datos que estoy completando mientras analizo un archivo plano.
Eso significa que está trabajando con un objeto desconectado, pero no está claro si está utilizando una asociación independiente o una asociación de clave externa .
Añadir
Al agregar una nueva entidad con un objeto secundario existente (objeto que existe en la base de datos), si EF no rastrea el objeto secundario, el objeto secundario se volverá a insertar. A menos que primero adjunte manualmente el objeto secundario.
Actualizar
Puede simplemente marcar la entidad como modificada, luego se actualizarán todas las propiedades escalares y las propiedades de navegación simplemente se ignorarán.
Diferencia de gráfico
Si desea simplificar el código cuando trabaja con un objeto desconectado, puede intentar graficar la biblioteca de diferencias .
Aquí está la introducción, Presentación de GraphDiff para Entity Framework Code First: permitir actualizaciones automáticas de un gráfico de entidades separadas .
Código de muestra
Inserte la entidad si no existe; de lo contrario, actualice.
Inserte la entidad si no existe, de lo contrario actualice E inserte el objeto secundario si no existe, de lo contrario actualice.
fuente
La mejor forma de hacerlo es anulando la función SaveChanges en su contexto de datos.
fuente
Tengo el mismo problema cuando intento guardar el perfil, ya tengo el saludo de mesa y soy nuevo para crear el perfil. Cuando inserto el perfil, también lo inserto en el saludo. Así que intenté así antes de savechanges ().
db.Entry (Profile.Salutation) .State = EntityState.Unchanged;
fuente
Esto funcionó para mí:
fuente
Lo que hemos hecho es antes de agregar el padre al dbset, desconectar las colecciones secundarias del padre, asegurándonos de enviar las colecciones existentes a otras variables para permitir trabajar con ellas más adelante y luego reemplazar las colecciones secundarias actuales con nuevas colecciones vacías. Establecer las colecciones secundarias en nulo / nada pareció fallar para nosotros. Después de hacer eso, agregue el padre al archivo dbset. De esta forma, los niños no se agregan hasta que usted lo desee.
fuente
Sé que es una publicación antigua, sin embargo, si está utilizando el enfoque de código primero, puede lograr el resultado deseado utilizando el siguiente código en su archivo de mapeo.
Esto básicamente le dirá a EF que excluya la propiedad "ChildObjectOrCollection" del modelo para que no se asigne a la base de datos.
fuente
Tuve un desafío similar al usar Entity Framework Core 3.1.0, mi lógica de repositorio es bastante genérica.
Esto funcionó para mí:
Tenga en cuenta que "ParentEntityId" es el nombre de la columna de clave externa en la entidad secundaria. Agregué la línea de código mencionada anteriormente en este método:
fuente