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