Как создать столбец в существующей таблице данных со значением по умолчанию только для обновления

#c# #ef-core-3.1

#c# #ef-core-3.1

Вопрос:

Я провожу крупный рефакторинг существующего проекта ASP-Core. Это приложение подключено к базе данных MS-SQL с использованием Entity Framework Core, подход Code First.

Я хотел бы добавить свойство, не допускающее обнуления, к a DbSet , которому по умолчанию будет присвоено определенное значение при выполнении обновления (чтобы отразить это изменение для ранее вставленных объектов), но не после выполнения обновления.

Мне удалось обновить существующие объекты, добавив defaultValue в migrationBuilder.AddColumn метод.

Проблема в том, что это значение по умолчанию сохраняется, т. Е.. если я попытаюсь позже добавить Foo без LastName, LastName будет по умолчанию передан в БД, а это не то, что я хочу (я бы хотел, чтобы БД вместо этого отклонила вставку).

Как я могу установить временное значение по умолчанию, используя подход Code First?

Единственный способ, который я нашел до сих пор, — это изменить значение по умолчанию для этого столбца из MS SQL Server Management Studio после применения этой миграции, что не идеально.

 //Existing version
public class Foo
{
    [Key]
    public int Id { get; set; }

    [MaxLength(240), Required]
    public string FirstName { get; set; }

}

//Updated version
public class Foo
{
    [Key]
    public int Id { get; set; }

    [MaxLength(240), Required]
    public string FirstName { get; set; }

    [MaxLength(240), Required]
    public string LastName { get; set; } //Should not be null
}

public partial class FooUpdateMigration : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder) {
        migrationBuilder.AddColumn<string>(
            name: "LastName",
            table: "Foos",
            maxLength: 240,
            nullable: false,
            defaultValue: "Unknown for old Foos");

    }

    protected override void Down(MigrationBuilder migrationBuilder) {
        migrationBuilder.DropColumn(
            name: "LastName",
            table: "Foos");
    }
}

public class FooManager
{

    public void AddFoo(ApplicationDbContext context)
    {
        Foo newFoo = new Foo(){
            FirstName="John",
            LastName = null
        };

        context.Foos.Add(newFoo);
        context.SaveChanges(); //DO NOT THROW EXCEPTION, LastName is defaulted to "Unknown for old Foos" into the datable
    }
}
 

Комментарии:

1. Я получаю эту ошибку «SQLException: не удается вставить значение NULL в столбец ‘LastName’, таблица ‘Foos’; столбец не допускает нулей. ОШИБКА вставки. » Как вы получаете значение по умолчанию, когда вы установили значение nullable: false в функции миграции Up?

2. @AribYousuf Я не уверен, что понимаю ваш вопрос. Я установил nullable = false И defaultValue = «строка по умолчанию» в функции миграции Вверх. Это значение по умолчанию присваивается столбцу в базе данных (я вижу его из MS SQL Server Manager)

3. К сожалению, я забыл добавить значение HasDefaultValue в функцию OnModelCreating , поэтому у меня это не работает, но я это исправил, и вы можете следовать моему ответу ниже.

Ответ №1:

Переопределите SaveChanges в классе DbContext и следуйте приведенному ниже коду:

     public override int SaveChanges()
    {
        foreach (Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry<Foo> entry in ChangeTracker.Entries<Foo>().Where(entry => entry.Entity.GetType().GetProperty("LastName") == null))
        {
            switch (entry.State)
            {
                case EntityState.Added:
                    entry.Entity.LastName = "Your value";
                    break;

                case EntityState.Modified:
                    entry.Entity.LastName = "Your value";
                    break;
            }
        }

        return base.SaveChanges();
    }
 

Комментарии:

1. Почему вы задаете значение для LastName? Это именно то, чего я не хочу, как объяснено в моем вопросе. Цитата: «Я бы хотел, чтобы БД вместо этого отклонила вставку».

2. Хорошо, тогда вместо вставки, каким должно быть поведение? Будет ли это вызывать исключение?