2010-06-10 54 views
15

Quiero recorrer una colección de objetos y agregarlos a una tabla. La tabla de destino tiene un campo de incremento automático. Si agrego un solo objeto, no hay problema. Si agrego dos objetos con la clave principal de cero, el marco de la entidad falla. Puedo especificar manualmente las claves principales, pero el objetivo de probar el EF fue hacer la vida más fácil, no más complicada. Aquí está el código y la excepción recibida a continuación.Autonumérico con Entity Framework

foreach (Contact contact in contacts) 
{    
    Instructor instructor = InstructorFromContact(contact);    
    context.AddToInstructors(instructor);    
} 

try 
{     
    context.SaveChanges();     
} 
catch (Exception ex) 
{ 
    Console.WriteLine(ex.ToString()); 
} 

El error es:

System.InvalidOperationException: Los cambios en la base de datos se cometieron con éxito, pero se ha producido un error al actualizar el contexto objeto. ObjectContext podría estar en un estado incoherente. Mensaje de excepción interno: los cambios de aceptación no pueden continuar porque los valores de las claves del objeto entran en conflicto con otro objeto en el ObjectStateManager. Asegúrese de que los valores clave sean únicos antes de llamando a AcceptChanges. en System.Data.Objects.ObjectContext.SaveChanges (opciones) SaveOptions
en System.Data.Objects.ObjectContext.SaveChanges() en DataMigration.Program.CopyInstructors() en C: \ Projects \ datamigration \ Program.cs : línea 52

+3

supongo que si usted acaba de dejar el campo Autonumérico en blanco, la base de datos asignará uno para usted cuando confirme. –

+0

Sí, funciona, agrega los registros y asignará claves principales, el problema es que no debería obtener una excepción para un escenario típico. Estoy seguro de que hay una forma 'correcta' de hacerlo dentro del marco, pero no estoy seguro de cómo. – dcompiled

+0

Bueno, ahora la excepción dejó de ser arrojada después de que hice algunos cambios misceláneos en la tabla y actualicé el modelo. No estoy seguro de qué hizo la diferencia. Los únicos cambios que hice fueron agregar algunos valores predeterminados para las columnas y establecer esas columnas para que no sean nulas. No estoy convencido de que los cambios estén relacionados con la excepción. – dcompiled

Respuesta

18

Establezca el atributo StoreGeneratedPattern en "Identidad" en su SSDL para el campo de autoincrement. Debería ayudar.

+7

Tenga en cuenta que no puede simplemente establecer esta propiedad en el diseñador, debe editar la sección SSDL a mano. Leí más allá de esta respuesta y pensé: "Ya lo hice", y seguí mirando, podría haber ahorrado horas al notar el * SSDL * Este es un error conocido en el diseñador. http://geeksharp.com/2010/05/27/ef4-bug-in-storegeneratedpattern-ssdl/ y http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/404d3017-01b7 -4129-8e05-f4aa48f15f08 – DanO

+0

es posible que desee opinar sobre esto: http://meta.stackexchange.com/questions/82509/should-accounts-used-by-multiple-users-be-allowed/82519#82519 – smartcaveman

+0

@Devart esto, no resolvió para mí ... – Campinho

12

Esto sucede porque a pesar de que se creó en la base de datos el valor generado automáticamente de la columna, EF nunca lo supo.

Entonces, para informarle a EF que la BD manejará el valor generado, debe abrir su archivo edmx (siempre uso el editor XML de VS para hacerlo) y en el lenguaje de definición de esquema de la tienda (SSDL) área, agregue el atributo StoreGeneratedPattern = "Identity" a la columna que necesita el patrón generado. De esta forma, EF lee el valor generado en el DB y lo almacena en la memoria caché.

Su tipo de definición de la entidad se verá más o menos así:

<EntityType Name="INVOICE"> 
      <Key> 
      <PropertyRef Name="CODE" /> 
      </Key> 
      <Property Name="CODE" Type="varchar" Nullable="false" 
       MaxLength="10" StoreGeneratedPattern="Identity"/>     
</EntityType> 

Tenga en cuenta que si quieres pasar a actualizar su modelo de todos estos cambios se perderán y que tendrá que repetir todo el proceso completo .

Esto funciona para EF 1.0, no estoy seguro si en EF4 todos estos problemas ya están solucionados.

+2

Creo que lo que salió mal es que inicialmente creé el modelo de la base de datos y olvidé establecer el campo de autonumeración. Más tarde edité mi base de datos y configuré esta propiedad, seguido del comando "actualizar el modelo desde la base de datos" en visual studio 2010. La función de actualización parece agregar nuevas propiedades, pero no estoy seguro de si 'corrige' correctamente las propiedades modificadas existentes. Al eliminar mi modelo y volver a crear desde cero, la función de autonumeración funcionó como se esperaba. Sin embargo, si lo hubiera sabido mejor, habría intentado tu idea. – dcompiled

+0

Actualmente (¡pero espero que pronto!) No estoy usando EF4, sin embargo, he leído algo en esta página que habla de esto: http://geeksharp.com/2010/05/27/ef4-bug-in-storegeneratedpattern-ssdl/ – cepriego

+2

Microsoft proporciona una revisión aquí para VS2010SP1. http://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=37957 Parece que funciona para mí. – kimsk

2

estoy usando EF6, para establecer el StoreGeneratedPattern, también puede probar el archivo EDMX abierta en Visual Studio, haga clic en la columna de datos en la tabla y seleccione Propiedades,

Entonces se puede establecer a partir de NoneIdentity en la ventana de propiedades: