Как я могу получить Id вставленной сущности в Entity Framework?
У меня проблема с Entity Framework в Asp.net. Я хочу получить значение Id всякий раз, когда я добавляю объект в базу данных. Как я могу это сделать?
12 ответов
Это довольно легко. Если вы используете сгенерированные БД идентификаторы (например, IDENTITY
в MS SQL) вам просто нужно добавить ObjectSet
а также SaveChanges
на связанных ObjectContext
, Id
будет автоматически заполнено для вас:
using (var context = new MyContext())
{
context.MyEntities.AddObject(myNewObject);
context.SaveChanges();
int id = myNewObject.Id; // Yes it's here
}
Структура сущности по умолчанию следует каждому INSERT
с SELECT SCOPE_IDENTITY()
когда автоматически генерируется Id
s используются.
Я использовал ответ Ладислава Мрнки для успешного получения идентификаторов при использовании Entity Framework, однако я публикую здесь, потому что я его не использовал (то есть использовал там, где это не требовалось) и думал, что я опубликую свои выводы здесь, Если люди хотят "решить" проблему, которая у меня была.
Рассмотрим объект Заказа, который имеет отношение внешнего ключа с Клиентом. Когда я добавил нового клиента и новый заказ одновременно, я делал что-то вроде этого;
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
Однако в моем случае это не требовалось, потому что у меня были отношения внешнего ключа между customer.Id и order.CustomerId
Все, что мне нужно было сделать, это;
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
Теперь, когда я сохраняю изменения, идентификатор, который генерируется для клиента, также добавляется в заказ. Мне не нужны дополнительные шаги
Я знаю, что это не отвечает на первоначальный вопрос, но я подумал, что это может помочь разработчикам, которые являются новичками в EF, чрезмерно использовать ответ с верхним голосом для чего-то, что может не потребоваться.
Вам необходимо перезагрузить объект после сохранения. Потому что он был изменен триггером базы данных, который не может быть отслежен EF. Так что нам нужно перезагрузить сущность снова из БД,
db.Entry(MyNewObject).GetDatabaseValues();
затем
int id = myNewObject.Id;
Посмотрите на ответ @jayantha в следующем вопросе:
Поиск @христианского ответа в следующем вопросе тоже может помочь:
Пожалуйста, обратитесь по этой ссылке.
http://www.ladislavmrnka.com/2011/03/the-bug-in-storegeneratedpattern-fixed-in-vs-2010-sp1/
Вы должны установить свойство StoreGeneratedPattern в идентичность и затем попробовать свой собственный код.
Или вы также можете использовать это.
using (var context = new MyContext())
{
context.MyEntities.AddObject(myNewObject);
context.SaveChanges();
int id = myNewObject.Id; // Your Identity column ID
}
Сохраняемый объект должен иметь правильный Id
после распространения изменений в базе данных.
Repository.addorupdate(entity, entity.id);
Repository.savechanges();
Var id = entity.id;
Это будет работать
Я сталкиваюсь с ситуацией, когда мне нужно вставить данные в базу данных и одновременно потребовать первичный идентификатор, используя структуру сущностей. Решение:
long id;
IGenericQueryRepository<myentityclass, Entityname> InfoBase = null;
try
{
InfoBase = new GenericQueryRepository<myentityclass, Entityname>();
InfoBase.Add(generalinfo);
InfoBase.Context.SaveChanges();
id = entityclassobj.ID;
return id;
}
Все ответы очень хорошо подходят для их собственных сценариев. Я отличался тем, что назначил int PK непосредственно из объекта (TEntity), который Add() возвратил в переменную int, подобную этой;
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
}
поэтому вместо создания нового объекта вы просто берете то, что хотите:)
РЕДАКТИРОВАТЬ Для г-на @GertArnold:
Вы можете получить идентификатор только после сохранения, вместо этого вы можете создать новый Guid и назначить перед сохранением.
Есть две стратегии:
Использовать базу данных
ID
(int
или жеGUID
)Минусы:
Вы должны выполнить
SaveChanges()
чтобы получитьID
для только что сохраненных объектов.Плюсы:
Можешь использовать
int
идентичность.Использовать сгенерированный клиент
ID
- только GUID.Плюсы: минификация
SaveChanges
операции. Возможность вставлять большой граф новых объектов за одну операцию.Минусы:
Разрешено только для
GUID
Когда вы сначала используете код EF 6.x
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
и инициализировать таблицу базы данных, он поместит
(newsequentialid())
внутри свойств таблицы под заголовком "Значение по умолчанию" или "Связывание", что позволяет заполнять идентификатор при его вставке.
Проблема в том, что если вы создадите таблицу и добавите
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
часть позже, будущие update-database не добавят обратно (newsequentialid())
Чтобы исправить это, нужно стереть миграцию, удалить базу данных и перенастроить... или вы можете просто добавить (newsequentialid()) в конструктор таблиц.
Я использую MySQL DB, и у меня есть идентификатор поля AUTO_INCREMENT .
Я столкнулся с той же проблемой с EF.
Я пробовал ниже строки, но он всегда возвращал 0.
await _dbContext.Order_Master.AddAsync(placeOrderModel.orderMaster);
await _dbContext.SaveChangesAsync();
int _orderID = (int)placeOrderModel.orderMaster.Id;
Но я понял свою ошибку и исправил ее.
Ошибка, которую я совершал: я передавал 0 в своей модели orderMaster для поля Id.
Решение сработало: как только я удалил поле Id из моей модели orderMaster , оно начало работать.
Я знаю, что это была очень глупая ошибка, но просто добавлю сюда, если кто-то пропустил это.