Универсальный репозиторий EF получает идентификатор из нового вставленного универсального объекта

Все мои объекты имеют идентификатор свойства. Все мои таблицы в базе данных имеют автоматически сгенерированный целочисленный идентификатор в качестве первичного ключа.

У меня есть общий метод для создания объектов.

Есть ли способ получить идентификатор объекта после того, как объект вставлен в базу данных?

   public override int Create<T>(T entity)
    {
        string entitySet = GetEntitySetName<T>();
        _context.AddObject(entitySet, entity);
        _context.SaveChanges();

        return <Id Here>; //TODO Return Id here
    }

В простом (не универсальном) репозитории я могу просто вернуть Entity.Id, но как добиться такого же поведения в универсальном репозитории? У меня может быть базовый класс сущностей для всех сущностей, которые содержат идентификатор свойства int, но есть ли способ заставить его работать без реализации этого наследования?


person angularrocks.com    schedule 23.08.2010    source источник


Ответы (4)


На самом деле это может быть очень просто;

// Project is is object/table, no POCO here.

var newProj = new Project();
newProj.Name = "Blah project";

var db = new AppDataContextname();

db.Projects.AddObject(newProj);

// at this point, newProj.ID is NOT set

db.SaveChanges(); // record is added to db.
// now, the ID property of the Project object is set!!!

// if the last ID in that table is '25', and you have auto-increment,
// then the object's ID property will now be 26!
Console.WriteLine(newProj.ID); // will output "26"

Долго ломал голову, как вернуть ID, пока не понял, что приведенный выше код работает. Работает в Linq-To-SQL и EF4.

person Graham    schedule 24.02.2011

С сущностями POCO вам придется использовать интерфейс, отражение или dynamic.

С сущностями EntityObject вы можете прочитать свойство EntityKey.

person Craig Stuntz    schedule 23.08.2010
comment
Спасибо, интерфейс лучше, но временно я выберу динамический. 'динамический currentEntity = сущность;' 'вернуть currentEntity.Id;' - person angularrocks.com; 23.08.2010

Решение:

 public override TR Create<T, TR>(T entity)
    {
        string entitySet = GetEntitySetName<T>();
        _context.AddObject(entitySet, entity);
        _context.SaveChanges();

        //Returns primaryKey value
        return (TR)context.CreateEntityKey(entitySet, entity).EntityKeyValues[0].Value;                       
    }

Где T: тип объекта, TR: тип объекта PK.

person angularrocks.com    schedule 05.01.2011
comment
Можно ли получить идентификатор перед вызовом savechanges? - person Jeroen; 21.04.2011
comment
@Jeroen Есть два способа сделать это: если вы хотите использовать int как PK, в этом случае сначала вам нужно вставить пустую запись, чтобы получить новый идентификатор, сгенерированный базой данных, в противном случае вы можете использовать Guid как PK, в этом случае вы можете сгенерируйте PK прямо в вашем коде, вызвав Guid.NewGuid() - person angularrocks.com; 22.04.2011
comment
пожалуйста, покажите, как вызвать вашу функцию Create(), которая вернет значение PK. Благодарность - person Monojit Sarkar; 03.08.2016

person    schedule
comment
Это работает, но может повлиять на производительность. Рефлексия медленная (многие утверждают). - person t_plusplus; 12.08.2015