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

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

Ответ 1

Это довольно легко. Если вы используете идентификаторы сгенерированных БД (например, IDENTITY в MS SQL), вам просто нужно добавить сущность к ObjectSet и SaveChanges в соответствующий ObjectContext. Id будет автоматически заполняться для вас:

using (var context = new MyContext())
{
  context.MyEntities.AddObject(myNewObject);
  context.SaveChanges();

  int id = myNewObject.Id; // Yes it here
}

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

Ответ 2

Я использовал Ladislav Mrnka 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

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

Ответ 3

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

db.Entry(MyNewObject).GetDatabaseValues();

затем

int id = myNewObject.Id;

Посмотрите на ответ @jayantha в следующем вопросе:

Как я могу получить идентификатор вставленной сущности в Entity Framework при использовании defaultValue?

Поиск @христианского ответа в следующем вопросе тоже может помочь:

Entity Framework Обновить контекст?

Ответ 4

Пожалуйста, обратитесь к этой ссылке.

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
}

Ответ 5

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

Ответ 6

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

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

Ответ 7

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

Ответ 8

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

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

Ответ 9

Есть две стратегии:

  1. Использовать сгенерированный базой данных ID (int или GUID)

    Минусы:

    Вы должны выполнить SaveChanges() чтобы получить ID только что сохраненных объектов.

    Плюсы:

    Можно использовать int идентичности.

  2. Используйте сгенерированный клиентом ID - только GUID.

    Плюсы: минимизация операций SaveChanges. Возможность вставлять большой граф новых объектов за одну операцию.

    Минусы:

    Разрешено только для GUID

Ответ 10

Все ответы очень хорошо подходят для их собственных сценариев, но я отличался тем, что назначил 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:

enter image description here

Ответ 11

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

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

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

(newsequentialid())

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

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

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]

часть позже, будущие update-database не добавят обратно (newsequentialid())

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