Как я могу получить идентификатор вставленного объекта в инфраструктуре Entity?


407

У меня проблема с Entity Framework в Asp.net. Я хочу получить значение Id, когда я добавляю объект в базу данных. Как я могу это сделать?

+11

Ответ Ладислава Мрнки ниже - правильный ответ и должен быть принят как таковой. 17 май. 162016-05-17 07:40:43

+1

OP только один раз опубликовал его с его/ее счетом, этот вопрос будет более конкретным. Это дало ему почти 2 тыс. Репутации (!), Ответ не отмечен как принятый beacause, поскольку учетная запись оставлена ​​с этого дня. 15 сен. 172017-09-15 19:48:18

8

Объект, который вы сохраняете, должен иметь правильный Id после распространения изменений в базе данных.

  0

У нас есть ошибка, например, «ошибка возникает при обновлении запроса. См. Внутреннее исключение для деталей» 06 мар. 112011-03-06 19:37:37

+25

Вы видели внутреннее исключение? ;-) 06 мар. 112011-03-06 20:02:00


691

Это довольно просто. Если вы используете идентификаторы сгенерированных БД (например, 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 
} 

рамки Entity по умолчанию после каждого INSERT с SELECT SCOPE_IDENTITY() когда используются автоматически генерируемые Id s.

+30

Итак, вы задаете неправильный вопрос. Если у вас есть проблема с исключением, вы должны задать вопрос, показывающий ваше исключение (и внутреннее исключение) и фрагмент кода, вызывающий эту ошибку. 06 мар. 112011-03-06 20:09:01

+1

Убедитесь, что объект, который вы добавляете, является действительным объектом, например, что-либо с ограничением базы данных «не null» должно быть заполнено и т. Д. 03 июн. 112011-06-03 09:35:44

+1

@LadislavMrnka: Как насчет свойств навигации вновь созданного объекта? Кажется, что после сохранения изменений они автоматически не заполняются. 11 ноя. 142014-11-11 18:21:15

  0

На самом деле, кажется, лениво загружается. 11 ноя. 142014-11-11 18:33:49

+2

Рассмотрим следующий сценарий: table1 должен генерировать идентификатор @@, чтобы использовать его в таблице2. Предполагается, что как таблица1, так и таблица2 должны находиться в одной транзакции, например. одна операция SaveChange должна сохранять данные таблицы. Идентификация @@ не будет сгенерирована, если не будет вызван «SaveChanges». как мы можем решить эту ситуацию? 23 ноя. 142014-11-23 23:09:40

  0

Сценарий внешнего ключа будет указан как свойство «myNewObject». Вы просто добавляете все объекты, необходимые для всех необходимых таблиц, ссылаясь друг на друга, если это необходимо перед сохранением. 25 фев. 152015-02-25 19:41:01

  0

И как я могу добавить несколько новых объектов? Если я, например, 3 AddObject в цикле, как я могу получить 3 новых идентификатора? 18 мар. 152015-03-18 07:41:31

  0

это работает для меня 06 сен. 152015-09-06 06:12:16

+1

Нет способа получить идентификатор до SaveChanges(), правильно? потому что мне нужен список всех вставленных объектов, и я не хочу сохранять для каждого объекта. 02 дек. 152015-12-02 18:19:14

+3

@Djeroen: Если вы используете Идентификатор, сгенерированный с помощью базы данных, вам нужно сначала вставить эти объекты в базу данных. Если вам нужно иметь идентификаторы перед вставкой, вы должны создать свою собственную логику для получения уникальных идентификаторов перед вставкой данных и не использовать столбец идентификаторов в базе данных. 03 дек. 152015-12-03 14:12:32

  0

Ненавижу, когда люди задают вопросы и не отмечают никакого правильного ответа. 21 ноя. 162016-11-21 09:58:37


10

См. Эту ссылку.

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 
} 
  0

То же, что и верхний проголосовавший ответ. 22 фев. 182018-02-22 17:56:53


18

Вам необходимо перезагрузить объект после сохранения. Потому что он был изменен с помощью триггера базы данных, который не может быть отслежен EF. Поэтому нам нужно перезагрузить объект снова из БД,

db.Entry(MyNewObject).GetDatabaseValues(); 

Тогда

int id = myNewObject.Id; 

Посмотрите @jayantha ответ на вопрос ниже:

How can I get Id of inserted entity in Entity framework when using defaultValue?

+1

Привет, когда мне это нравится, я получаю ошибку компиляции, которая говорит: не удается разрешить свойства, например, Id или Name, можете ли вы мне помочь? 17 окт. 142014-10-17 05:41:27

  0

@MortezaAzizi Кажется, что это ошибка не обработанной или пустой ошибки свойства, но можете ли вы, пожалуйста, объяснить или написать фрагмент кода? 18 окт. 142014-10-18 08:54:29


1

я сталкиваюсь с ситуацией где мне нужно вставить данные в базу данных &, одновременно требуется первичный идентификатор, использующий структуру сущностей. Решение:

long id; 
IGenericQueryRepository<myentityclass, Entityname> InfoBase = null; 
try 
{ 
    InfoBase = new GenericQueryRepository<myentityclass, Entityname>(); 
    InfoBase.Add(generalinfo); 
    InfoBase.Context.SaveChanges(); 
    id = entityclassobj.ID; 
    return id; 
} 

4
Repository.addorupdate(entity, entity.id); 
Repository.savechanges(); 
Var id = entity.id; 

Это будет работать.

+1

Репозиторий не несет ответственности за сохранение изменений в базе данных. Это работа UnitOfWork. 11 ноя. 172017-11-11 10:55:32


37

Я использовал Ladislav Mrnka's answer, чтобы успешно получить идентификаторы при использовании Entity Framework, но я размещаю здесь, потому что я пропустил его (т. Е. Использовал его там, где он не был нужен), и подумал, что я опубликую мои результаты здесь в случае, если люди хотят «решить» мою проблему.

Рассмотрите объект Order, у которого есть внешние ключи с Клиентом. Когда я добавил нового клиента и новый заказ, в то же время я делал что-то вроде этого;

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, из-за использования голосового ответа сверху для чего-то, что может требуются.

+2

Спасибо! ВАЖНАЯ рекомендательная рекомендация: var order = new Заказ {Customer = customer}; Это показывает способность Entity Framework назначать связанный объект, и идентификатор будет автоматически обновляться. 09 июл. 172017-07-09 19:06:17

  0

спасибо за конкретное указание этого. Я делал по умолчанию. + 1ed 19 сен. 172017-09-19 05:33:51


3

Вы можете получить идентификатор только после сохранения, вместо этого вы можете создать новый указатель и назначить его перед сохранением.


0

При использовании EF кода 6.x первого

[DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public Guid Id { get; set; } 

и инициализировать таблицу базы данных, он поставит

(newsequentialid()) 

внутри свойств таблицы под заголовком Значение по умолчанию или Binding, что позволяет идентификатор, который будет заполнен, когда он вставлен.

Проблема заключается в том, если вы создаете таблицу и добавьте

[DatabaseGenerated(DatabaseGeneratedOption.Identity)] 

часть позже, будущие обновления-базы данных не добавит назад (NEWSEQUENTIALID())

Чтобы исправить правильный путь для удаления миграции, удаления базы данных и повторной миграции ... или вы можете просто добавить (newsequentialid()) в конструктор таблиц.