Tengo un problema con Entity Framework en Asp.net. Quiero obtener el valor de Id cada vez que agrego un objeto a la base de datos. ¿Cómo puedo hacer esto?
SaveChanges
inmediato solo para obtener la identificación. Lectura adicional aquí .
Tengo un problema con Entity Framework en Asp.net. Quiero obtener el valor de Id cada vez que agrego un objeto a la base de datos. ¿Cómo puedo hacer esto?
SaveChanges
inmediato solo para obtener la identificación. Lectura adicional aquí .
Respuestas:
Es bastante fácil Si está utilizando DB genera identificadores (como IDENTITY
en MS SQL) sólo tiene que añadir a la entidad ObjectSet
y SaveChanges
sobre las enfermedades relacionadas ObjectContext
. Id
será llenado automáticamente por usted:
using (var context = new MyContext())
{
context.MyEntities.Add(myNewObject);
context.SaveChanges();
int id = myNewObject.Id; // Yes it's here
}
El marco de la entidad por defecto sigue a cada uno INSERT
con SELECT SCOPE_IDENTITY()
cuando Id
se utilizan s generados automáticamente .
Había estado usando la respuesta de Ladislav Mrnka para recuperar con éxito los identificadores cuando usaba el Entity Framework, sin embargo, estoy publicando aquí porque había estado usándolo mal (es decir, usándolo donde no era necesario) y pensé que publicaría mis hallazgos aquí en caso la gente está buscando "resolver" el problema que tuve.
Considere un objeto Order que tenga una relación de clave externa con el Cliente. Cuando agregué un nuevo cliente y un nuevo pedido al mismo tiempo, estaba haciendo algo como esto;
var customer = new Customer(); //no Id yet;
var order = new Order(); //requires Customer.Id to link it to customer;
context.Customers.Add(customer);
context.SaveChanges();//this generates the Id for customer
order.CustomerId = customer.Id;//finally I can set the Id
Sin embargo, en mi caso, esto no era necesario porque tenía una relación de clave externa entre customer.Id y order.CustomerId
Todo lo que tenía que hacer era esto;
var customer = new Customer(); //no Id yet;
var order = new Order{Customer = customer};
context.SaveChanges();//adds customer.Id to customer and the correct CustomerId to order
Ahora, cuando guardo los cambios, la identificación que se genera para el cliente también se agrega al pedido. No necesito los pasos adicionales.
Soy consciente de que esto no responde a la pregunta original, pero pensé que podría ayudar a los desarrolladores que son nuevos en EF a usar en exceso la respuesta más votada para algo que puede no ser necesario.
Esto también significa que las actualizaciones se completan en una sola transacción, evitando potencialmente los datos de orphin (todas las actualizaciones se completan o ninguna lo hace).
Debe volver a cargar la entidad después de guardar los cambios. Porque ha sido alterado por un disparador de base de datos que EF no puede rastrear. Entonces, necesitamos volver a cargar la entidad desde la base de datos,
db.Entry(MyNewObject).GetDatabaseValues();
Entonces
int id = myNewObject.Id;
Mira la respuesta de @jayantha en la siguiente pregunta:
¿Cómo puedo obtener el Id. De la entidad insertada en Entity Framework cuando uso defaultValue?
Mirar la respuesta @christian en la siguiente pregunta también puede ayudar:
.GetDatabaseValues();
si acaba de guardar su modelo en la base de datos. La ID debe repoblarse al modelo automáticamente.
GetDatabaseValues()
si no conoce la ID del objeto a buscar en la base de datos?
Por favor, consulte este enlace.
http://www.ladislavmrnka.com/2011/03/the-bug-in-storegeneratedpattern-fixed-in-vs-2010-sp1/
Debe establecer la propiedad de StoreGeneratedPattern en identidad y luego probar su propio código.
O también puedes usar esto.
using (var context = new MyContext())
{
context.MyEntities.AddObject(myNewObject);
context.SaveChanges();
int id = myNewObject.Id; // Your Identity column ID
}
StoreGeneratedPattern
fue la pieza que faltaba para mí.
Puede obtener ID solo después de guardar, en su lugar, puede crear un nuevo Guid y asignarlo antes de guardar.
Me encuentro con una situación en la que necesito insertar los datos en la base de datos y, al mismo tiempo, necesito la identificación principal utilizando el marco de la entidad. Solución:
long id;
IGenericQueryRepository<myentityclass, Entityname> InfoBase = null;
try
{
InfoBase = new GenericQueryRepository<myentityclass, Entityname>();
InfoBase.Add(generalinfo);
InfoBase.Context.SaveChanges();
id = entityclassobj.ID;
return id;
}
Todas las respuestas son muy adecuadas para sus propios escenarios, lo que hice diferente es que asigné la PK int directamente desde el objeto (TEntity) que Add () devolvió a una variable int como esta;
using (Entities entities = new Entities())
{
int employeeId = entities.Employee.Add(new Employee
{
EmployeeName = employeeComplexModel.EmployeeName,
EmployeeCreatedDate = DateTime.Now,
EmployeeUpdatedDate = DateTime.Now,
EmployeeStatus = true
}).EmployeeId;
//...use id for other work
}
así que en lugar de crear un objeto completamente nuevo, simplemente toma lo que quieras :)
EDITAR Para el Sr. @GertArnold:
Add
(si es así DbSet.Add
) no asigna mágicamente un valor a EmployeeId
.
SaveChanges
. Imposible. A menos que tenga algún otro proceso que asigne EmployeeId
, por ejemplo, en Employee
el constructor. O estás usando EF core ForSqlServerUseSequenceHiLo
. De todos modos, no estás dando la imagen completa.
Repository.addorupdate(entity, entity.id);
Repository.savechanges();
Var id = entity.id;
Esto funcionará
Repository
es. ¡Y "esto funcionará" es una explicación!
Hay dos estrategias:
Usar generado por la base de datos ID
( int
o GUID
)
Contras:
Debe realizar SaveChanges()
para obtener las ID
entidades recién guardadas.
Pros:
Puede usar int
identidad.
Usar cliente generado ID
- solo GUID.
Pros: Minificación de SaveChanges
operaciones. Capaz de insertar un gran gráfico de nuevos objetos por una operación.
Contras:
Permitido solo para GUID
Cuando usa el código EF 6.x primero
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
e inicializar una tabla de base de datos, pondrá un
(newsequentialid())
dentro de las propiedades de la tabla debajo del encabezado Valor predeterminado o Enlace, lo que permite que la ID se complete a medida que se inserta.
El problema es si crea una tabla y agrega el
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
parte posterior, las futuras bases de datos de actualización no volverán a agregar el (newsequentialid ())
Para corregir la forma correcta es borrar la migración, eliminar la base de datos y volver a migrar ... o simplemente puede agregar (newsequentialid ()) en el diseñador de la tabla.
when -column- is NULL, then NEWID()