Как я могу добавить значения по умолчанию для свойства при сохранении с помощью Code First EF4.1?

Я начал с создания таких моделей, как это:

public abstract class EditableBase
{
    public DateTime CreatedOn { get; set; }
    public DateTime ModifiedOn { get; set; }

    public int CreatedBy { get; set; }
    public int ModifiedBy { get; set; }
}

public class Project : EditableBase
{
    public int ProjectId { get; set; }
    public string ProjectName { get; set; }
}

И я использую эту строку при запуске приложения:

Database.SetInitializer<ModelContext>(
            new DropCreateDatabaseIfModelChanges<ModelContext>());

Таблица, называемая Projects, создается со всеми перечисленными выше свойствами в качестве столбцов... это именно то, что я хотел.

Однако теперь мне нужно заполнить некоторые значения по умолчанию, когда я выдаю SaveChanges() в DbContext. Когда я сохраняю, мне нужно обновить свойства ModifiedOn и ModifiedBy с соответствующими значениями.

Обычно я бы, по крайней мере, имел значения DateTime на стороне базы данных (либо триггер, либо хранимую процедуру), но это, очевидно, не является вариантом здесь, поскольку база данных будет удалена при изменении класса. И так как я сначала сделал код, у меня нет модельного дизайнера, который я могу настроить.

Что я хотел бы сделать, так это добавить метод в класс EditableBase, который вызывается при выполнении SaveChanges(), тем самым сохраняя всю логику в одном месте. Можно ли сделать это? Каков наилучший способ достичь моей цели?

Ответ 1

Переопределить SaveChanges в производном DbContext:

public override int SaveChanges()
{
    foreach(var entry in ChangeTracker.Entries<EditableBase>())
    {
        var entity = entry.Entity;
        if (entry.State == EntityState.Added)
        {
            entity.CreatedOn = ...;
            entity.CreatedBy = ...;
        }
        else if (entry.State == EntityState.Modified)
        {
            entity.ModifiedOn = ...;
            entity.ModifiedBy = ...;
        }
    }

    return base.SaveChanges();
}

Я не уверен, будет ли общий Entries работать непосредственно с вашим базовым типом, потому что он фактически не отображается как базовый объект. Существует также не общая версия, поэтому вы можете переписать ее на более сложный запрос linq или протестировать каждый тип сущности записи в цикле.

Ответ 2

Ну, у вас есть полный контроль над кодом для ваших объектов. Я бы предположил, что вы, вероятно, захотите реализовать подобный шаблон IPropertyChanged для обновления своих свойств.

Ответ 3

Рассматривал ли два параметра в этот пост, где вы что-то делаете на установщике (или конструкторе)?

Решение по умолчанию для атрибутов кажется хорошим.