Código del Entity Framework Primer método AddOrUpdate insertar valores duplicados

Tengo una entidad simple:

public class Hall { [Key] public int Id {get; set;} public string Name [get; set;} } 

Luego en el método Seed utilizo AddOrUpdate para llenar la tabla:

 var hall1 = new Hall { Name = "French" }; var hall2 = new Hall { Name = "German" }; var hall3 = new Hall { Name = "Japanese" }; context.Halls.AddOrUpdate( h => h.Name, hall1, hall2, hall3 ); 

Luego corro en la consola de administración de paquetes:

 Add-Migration Current Update-Database 

Está todo bien: tengo tres filas en la mesa “Hall”. Pero si vuelvo a ejecutar en la Update-Database Package Management Console ya tengo cinco filas:

 Id Name 1 French 2 Japaneese 3 German 4 French 5 Japanese 

¿Por qué? Creo que debería ser tres filas otra vez, no cinco. Traté de usar la propiedad Id lugar de Name pero no hace la diferencia.

ACTUALIZAR:

Este código produce el mismo resultado:

 var hall1 = new Hall { Id = 1, Name = "French" }; var hall2 = new Hall { Id = 2, Name = "German" }; var hall3 = new Hall { Id = 3, Name = "Japanese" }; context.Halls.AddOrUpdate( h => h.Id, hall1); context.Halls.AddOrUpdate( h => h.Id, hall2); context.Halls.AddOrUpdate( h => h.Id, hall3); 

También tengo el último EntityFramework instalado a través de nuget.

Ok, me estaba golpeando la cara con el teclado durante una hora con esto. Si el campo Id de su tabla es un campo de Identidad, entonces no funcionará, por lo tanto, use uno diferente para identifierExpression. Usé la propiedad Name y también eliminé el campo Id del new Hall {...} inicializador new Hall {...} .

Este ajuste al código OPs funcionó para mí, así que espero que ayude a alguien:

 protected override void Seed(HallContext context) { context.Halls.AddOrUpdate( h => h.Name, // Use Name (or some other unique field) instead of Id new Hall { Name = "Hall 1" }, new Hall { Name = "Hall 2" }); context.SaveChanges(); } 

Este código funciona:

 public Configuration() { AutomaticMigrationsEnabled = true; } protected override void Seed(HallContext context) { context.Halls.AddOrUpdate( h => h.Id, new Hall { Id = 1, Name = "Hall 1" }, new Hall { Id = 2, Name = "Hall 2" }); context.SaveChanges(); } 

Sé que esta es una pregunta antigua, pero la respuesta correcta es que si está configurando el id # usted mismo y desea utilizar AddOrUpdate, entonces debe decirle a EF / SQL que no desea que genere el ID #.

 modelBuilder.Entity().Property(p => p.Id) .HasDatabaseGeneratedOption(System.ComponentModel .DataAnnotations.Schema.DatabaseGeneratedOption.None); 

La desventaja de esto es que cuando insertas un nuevo ítem necesitas configurarlo, por lo que si esto se hace dinámicamente en tiempo de ejecución (en lugar de datos de inicialización), entonces tendrás que calcular el siguiente Id. Context.MyClasses.Max(c=>c.Id) + 1 funciona bien.

Esto también puede ser causado si está configurando el estado de la entidad incorrectamente. Seguí recibiendo el siguiente error cuando ejecutaba la actualización de la base de datos … “La secuencia contiene más de un elemento coincidente”.

Por ejemplo, tenía filas duplicadas creadas en cada comando de base de datos de actualización (que, por supuesto, no se supone que ocurra al generar datos), y luego el siguiente comando de base de datos de actualización no funcionó porque encontró más de una coincidencia (de ahí el error de secuencia que dice que tengo más de una fila coincidente). Esto se debe a que anulé SaveChanges en mi archivo de contexto con una llamada a ApplyStateChanges …

 public override int SaveChanges() { this.ApplyStateChanges(); return base.SaveChanges(); } 

Estaba usando ApplyStateChanges para garantizar que al agregar gráficos de objetos, Entity Framework sepa explícitamente si el objeto está en un estado agregado o modificado. La explicación completa de cómo estoy usando ApplyStateChanges se puede encontrar aquí .

Y esto funciona muy bien (¡pero la advertencia!) … si también está siembrando la base de datos utilizando las migraciones de CodeFirst, entonces el método anterior causará esgulps en la llamada AddOrUpdate () dentro del método Seed. Antes que nada, simplemente revise su archivo DBContext y asegúrese de no anular SaveChanges en el camino anterior, o terminará obteniendo datos duplicados ejecutando el comando update-database por segunda vez, y luego no funcionará en absoluto. tercera vez, ya que hay más de una fila por cada elemento coincidente.

Cuando se trata de eso, no necesita configurar el Id en AddOrUpdate () … que anula todo el propósito de la creación de bases de datos fácil e inicial. Funciona bien por algo como:

 context.Students.AddOrUpdate( p => p.StudentName, new Student { StudentName = "Bill Peters" }, new Student { StudentName = "Jandra Nancy" }, new Student { StudentName = "Rowan Miller" }, new Student { StudentName = "James O'Dalley" }, 

SOLAMENTE MIENTRAS no anulo el método SaveChanges en mi archivo de contexto con una llamada a ApplyStateChanges. Espero que esto ayude.

Esto funcionó para mí

  1. Eliminar todas las filas en la tabla.
  2. Restablezca la identidad incremental a 0. DBCC CHECKIDENT (yourtablename, RESEED, 0) (Las claves principales especificadas en Seed() deben coincidir con las de la tabla de la base de datos para que no se dupliquen).
  3. Especifique las claves principales en el método ‘semilla’.
  4. Ejecute el método Seed() varias veces y compruebe si se duplicaron.

Descubrí que AddOrUpdate funciona bien con campos que no son ID. Si esto funciona para usted: context.Halls.AddOrUpdate(h => h.Name, hall1, hall2, hall3)

Es posible que desee utilizar nombres de Hall como ‘French_test_abc_100’, ‘German_test_abc_100’, etc.

Esto evita que los datos de prueba codificados dificulten las cosas cuando prueba su aplicación.

Si la ID del objeto (hall) es 0, es una inserción. Creo que necesitas verificar dos veces el campo de identificación de tus objetos del pasillo

¿Tu campo de ID es un campo de Identidad? Me encontré con este mismo problema. Cuando eliminé el estado de Identidad de mi campo ID y establecí los ID en la base de datos, eso resolvió el problema.

Eso funcionó para mí, ya que estas eran tablas de búsqueda y no deberían haber sido campos de identidad, de todos modos.

Creo que es probable que tenga que anular las migraciones de bases de datos existentes (es decir, iniciar su base de datos desde cero) con algo como ‘Update-Database TargetMigration: 0’ seguido de ‘Update-Database’.

Tal como están las cosas, no estás eliminando la tabla o los valores existentes, solo agregas / actualizas esos valores. Eso debe suceder para obtener el resultado deseado.

Aquí hay una buena referencia para las migraciones de EF: http://elegantcode.com/2012/04/12/entity-framework-migrations-tips/

Utilicé el campo ID como Identidad / Clave y agregué atributos para no asignar Ids al servidor. Esto resolvió mi problema.

 public class Hall { [Key] [Required] [DatabaseGenerated(DatabaseGeneratedOption.None)] public int Id {get; set;} public string Name [get; set;} } 

Solo a la respuesta de Ciaren, el siguiente código para restablecer el contexto en ModelCreating, me ayudó a resolver problemas similares. Asegúrese de cambiar “ApplicationContext” a su nombre DbContext.

 public class ApplicationContext : DbContext, IDbContext { public ApplicationContext() : base("ApplicationContext") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove(); Database.SetInitializer(null); base.OnModelCreating(modelBuilder); } } 

También podrías haber hecho esto:

  context.Halls.AddOrUpdate(new Hall[]{hall1,hall2, hall3}); 

Descubrí que para que esto funcione, la posición de identidad debe ser 0 cuando se ejecuta la semilla por primera vez. Puedes restablecerlo usando:

 DBCC CHECKIDENT (tableName, RESEED, 0)