2010-07-06 31 views
23

estoy aprendiendo Marco de la entidad bajo VC# 2010.C#, marco de la entidad, incremento automático

He creado una tabla simple con fines de aprendizaje, uno de los campos es "ID" de tipo entero, la identidad establecida en true . He generado Entity Data Model de esa tabla y lo he conectado con dataGridView. El problema es que no se incrementa automáticamente: cada fila insertada quiere ser id = 0 (lo cual es imposible, por supuesto, ya que id debe ser único)

¿Qué estoy haciendo mal? ¿Cómo debo configurar EF o SQL DB en sí?

Respuesta

35

Compruebe en su modelo EDMX, que el atributo StoreGeneratedPattern del campo de autoincrement está establecido en "Identity". De esta forma, EF sabe que los autonumbers son manejados por el DB.

Aquí esto se explica mejor: Autonumber with Entity Framework

+0

Sí, generalmente a partir de las piezas generadas VS2010 tendrá que establecer el Valor StoreGenerated en el bloque grande superior de xml. Obtendrá varias claves primarias porque, a menos que lo cambie, EF genera la ID para usted, como 0. – Rangoric

+5

Es una locura que todavía no hayan resuelto este error omnipresente. ¡Es la versión 4, vamos equipo de EF! – arviman

+1

Muchas veces, las personas olvidan marcar la columna con un valor de identidad e incremento automático. EF lo recoge de la base de datos. – arviman

1

Asegúrese de estar guardando sus entidades en la base de datos antes de intentar leer el valor de Id autoincrementado.

Su Id. No se establecerá por incremento automático hasta la primera vez que se guarde en la base de datos.

+2

el problema es, que si bien llamando SaveChanges (después de la adición de varias filas) lanza una excepción sobre la clave primaria duplicada ... – migajek

+0

@vic - Interesante. ¿Estás seguro de que está fallando en el inserto para la tabla de claves de aumento automático? –

1

Sí. LINQ to SQL se comporta de la misma manera. La identificación no se establecerá hasta que se guarde en la base de datos. Hasta que lo haga, todos los ID serán cero (como ya ha visto).

2

La identidad no se ha establecido y se incrementa simplemente añadiendo al conjunto de entidades ... La entidad no se graba con el PP hasta que llame context.SaveChanges() ...

db.AddToUserSet(user);//Added to EF entity collection 
db.SaveChanges();//INSERT executed in db, Identity set and incremented. 
+6

el problema es que al llamar a SaveChanges (después de agregar varias filas) arroja una excepción sobre la clave principal duplicada ... – migajek

0

tuve problemas similares, que se produjo en EF6 (funcionaba en EF4 sin transacciones, EF 4 utilizadas transacciones implícitas con el alcance derecha).

Solo crear una nueva entidad y guardarla no me ayudó en mi caso (ver los comentarios de las otras respuestas, tenían problemas similares con el uso de dc.SaveChanges() solo para la actualización automática).

Consideremos el siguiente código (CustomerId es la clave principal con incremento automático):

public void UpdateCustomer(string strCustomerName, string strDescription) 
{ 
    using (var transaction = CreateTransactionScope()) 
    { 
    MyCustomer tbl=null; 
    Func<MyCustomer, bool> selectByName=(i => i.CustomerName.Equals(strCustomerName)); 
    var doesRecordExistAlready = dc.MyCustomers.Any(selectByName); 
    if (doesRecordExistAlready) 
    { 
     // Updating 
     tbl=dc.MyCustomers.Where(selectByName).FirstOrDefault();   
     tbl.Description=strDescription; 
    } 
    else 
    { 
     // Inserting 
     tbl=new MyCustomer(); 
     var maxItem= 
      dc.MyCustomers.OrderByDescending(i => i.CustomerId).FirstOrDefault(); 
     var newID = maxItem==null ? 1 : maxItem.CustomerId+1; 
     tbl.CustomerId=newID; 
     tbl.CustomerName=strCustomerName; 
     tbl.Description=strDescription; 
     dc.MyCustomers.AddObject(tbl);  
    } 
    dc.SaveChanges(); // save all changes consistently   
    transaction.Complete(); // commit 
    } 
} 

Y la función de ayuda para crear el contexto de transacción correcta es:

// creates the right transaction scope 
public static System.Transactions.TransactionScope CreateTransactionScope() 
    // needs to add ref: System.Transactions 
{ 
    var transactionOptions = new TransactionOptions 
    { 
     IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted, 
     Timeout = new TimeSpan(0,0,10,0,0) //assume 10 min is the timeout time 
    }; 
    var scopeOption=TransactionScopeOption.RequiresNew; 
    var scope = new System.Transactions.TransactionScope(scopeOption, 
       transactionOptions); 
    return scope; 
} 

El truco está aquí , para permitir la lectura no confirmada, por lo tanto, puede consultar la ID máxima y agregar 1 a la ID. Lo que no pude lograr es permitir que SQL Server genere el ID automáticamente, porque EF me permite no omitir el CustomerId al momento de la creación.

Para leer más acerca ámbito de transacción, look here.

Cuestiones relacionadas