Подтвердить что ты не робот

Получить все отслеживаемые объекты из DbContext?

Многие из таблиц в моей базе данных должны иметь столбец "DateCreated" и "DateModified". Я хочу обновлять эти столбцы всякий раз, когда вызывается SaveChanges().

Все мои объекты модели наследуют от класса AbstractModel, чтобы разрешить такое поведение. Класс выглядит следующим образом:

public abstract class AbstractModel {
    public virtual void UpdateDates() { }
}

Затем я планирую переопределить UpdateDates() в любых дочерних классах, у которых есть поля DateCreated и DateModified, которые они должны поддерживать.

Чтобы использовать это, мне нужно получить список всех объектов, которые отслеживает DbContext, и вызвать UpdateDates() на них, если объект помечен как Added или Modified.

Кажется, я не могу получить доступ к тому, где DbContext хранит эту информацию. Я могу сделать dbContext.Entry(object).State, чтобы получить EntityState одного объекта, но я не могу понять, как получить список всех отслеживаемых объектов.

Как это сделать?

4b9b3361

Ответ 1

Я думаю, вы можете использовать ChangeTracker для этого:

public class MyContext : DbContext
{
    //...

    public override int SaveChanges()
    {
        foreach (var dbEntityEntry in ChangeTracker.Entries<AbstractModel>())
        {
            dbEntityEntry.Entity.UpdateDates();
        }
        return base.SaveChanges();

    }
}

Ответ 2

Принятое решение здесь лучше для выше EF4, чем предложение ObjectContext - мы столкнулись с проблемами, например, в памяти db, которую мы использовали в тестовом контексте, не работающем хорошо с вышеупомянутым решением (получение состояния "Отдельно" для некоторых измененных записей в сценариях наследования). Это решение использует собственный способ DbContext для поиска отслеживаемых объектов:

context.ChangeTracker.Entries()
        .Where (t => t.State == EntityState.Modified)

Ответ 3

Это хорошо работает в нашем проекте, поэтому нам не нужно забывать переопределять что-то каждый раз, когда мы добавляем новый объект, у которого есть наше стандартное свойство LastUpdatedDateTime. Использование EF4; для EF5 DbContext я думаю ((IObjectContextAdapter) _dbContext).ObjectContext.ObjectStateManager предоставит вам диспетчер состояний объекта:

// In our SaveChanges wrapper:
        var entries = context.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Deleted);

        private static void PopulateDate(IEnumerable<ObjectStateEntry> entries)
                {
                    foreach (var entry in entries)
                    {
                        if (entry.State != EntityState.Deleted)
                        {
                            if ((entry.Entity != null) && (entry.Entity.GetType().GetProperty("LastUpdatedDateTime") != null))
                            {
                                ((dynamic)entry.Entity).LastUpdatedDateTime = DateTime.UtcNow;
                            }
                        }
                    }
                }

Вызов отражения не является проблемой: для объекта с 25 свойствами (много), миллион запросов отражения принимает avg ~ 210 мс.