Eu adicionei a [Required]
anotação de dados a um dos meus modelos em um aplicativo ASP.NET MVC . Depois de criar uma migração, a execução do Update-Database
comando resulta no seguinte erro:
Não é possível inserir o valor NULL na coluna 'Diretor', tabela 'MOVIES_cf7bad808fa94f89afa2e5dae1161e78.dbo.Movies'; coluna não permite nulos. UPDATE falha. A instrução foi encerrada.
Isso se deve ao fato de alguns registros possuírem NULL em suas Director
colunas. Como posso alterar automaticamente esses valores para algum diretor padrão (digamos "John Doe")?
Aqui está meu modelo:
public class Movie
{
public int ID { get; set; }
[Required]
public string Title { get; set; }
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[Required]
public string Genre { get; set; }
[Range(1,100)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }
[StringLength(5)]
public string Rating { get; set; }
[Required] /// <--- NEW
public string Director { get; set; }
}
e aqui está minha última migração:
public partial class AddDataAnnotationsMig : DbMigration
{
public override void Up()
{
AlterColumn("dbo.Movies", "Title", c => c.String(nullable: false));
AlterColumn("dbo.Movies", "Genre", c => c.String(nullable: false));
AlterColumn("dbo.Movies", "Rating", c => c.String(maxLength: 5));
AlterColumn("dbo.Movies", "Director", c => c.String(nullable: false));
}
public override void Down()
{
AlterColumn("dbo.Movies", "Director", c => c.String());
AlterColumn("dbo.Movies", "Rating", c => c.String());
AlterColumn("dbo.Movies", "Genre", c => c.String());
AlterColumn("dbo.Movies", "Title", c => c.String());
}
}
fonte
IS NULL
verificação por sua consulta."'John Doe'"
- você precisa usar aspas SQL.AlterColumn
atualizar os valores atuais? É um comando DDL (não DML).Além da resposta de @webdeveloper e @Pushpendra, você precisa adicionar manualmente as atualizações à sua migração para atualizar as linhas existentes. Por exemplo:
Isso ocorre porque
AlterColumn
produz DDL para definir o padrão da coluna para algum valor específico na especificação da tabela. O DDL não afeta as linhas existentes no banco de dados.Na verdade, você está fazendo duas alterações ao mesmo tempo (definindo o padrão e tornando a coluna NOT NULL) e cada uma delas é válida individualmente, mas como você está fazendo as duas ao mesmo tempo, pode esperar que o sistema ' de forma inteligente 'perceba sua intenção e defina todos
NULL
valores com o valor padrão, mas isso não é o que se espera o tempo todo.Suponha que você esteja apenas definindo o valor padrão para a coluna, e não tornando-o NÃO NULO. Obviamente, você não espera que todos os registros NULL sejam atualizados com o padrão fornecido.
Então, na minha opinião, isso não é um bug, e eu não quero que a EF atualize meus dados da maneira que eu não digo explicitamente para fazer. O desenvolvedor é responsável por instruir o sistema sobre o que fazer com os dados.
fonte
fonte
não tenho certeza se esta opção estava sempre disponível, mas apenas encontrei um problema semelhante, descobri que consegui definir o valor padrão sem executar nenhuma atualização manual usando o seguinte
defaultValueSql: "'NY'"
Recebi um erro quando o valor fornecido era,
"NY"
então percebi que eles estavam esperando um valor SQL como"GETDATE()"
eu tentei"'NY'"
e isso funcionoutoda a linha se parece com isso
AddColumn("TABLE_NAME", "State", c => c.String(maxLength: 2, nullable: false, defaultValueSql: "'NY'"));
Graças a esta resposta , me colocou no caminho certo
fonte
Desde EF Core 2.1, você pode usar
MigrationBuilder.UpdateData
para alterar os valores antes de alterar a coluna (mais limpo do que usar SQL bruto):fonte
Descobri que apenas usar o Auto-Property Initializer na propriedade da entidade é suficiente para fazer o trabalho.
Por exemplo:
fonte
Muitas das outras respostas se concentram em como intervir manualmente quando esses problemas ocorrem.
Lembre-se de que as alterações manuais aplicadas a um script de migração serão sobrescritas se você reorganizar a migração. Para a primeira solução, é muito fácil estender o EF para definir um valor padrão em um campo automaticamente como parte da geração da migração.
A solução a seguir combina notação de atributo, convenções de configuração de modelo e anotações de coluna para passar metadados para um gerador de código de migração customizado. As etapas 1 e 2 podem ser substituídas por notação fluente para cada campo afetado se você não estiver usando notação de atributo.
Existem muitas técnicas em jogo aqui, fique à vontade para usar algumas ou todas, espero que haja valor para todos aqui
Declare o valor padrão
Crie ou reaproveite um atributo existente para definir o valor padrão a ser usado, para este exemplo, criaremos um novo atributo chamado DefaultValue que herda de ComponentModel.DefaultValueAttribute, pois o uso é intuitivo e existe uma chance de que existente as bases de código já implementam este atributo. Com esta implementação, você só precisa usar este atributo específico para acessar DefaultValueSql, que é útil para datas e outros cenários personalizados.
Implementação
Definição de Atributo
Crie uma convenção para injetar o valor padrão nas anotações da coluna As anotações da
coluna são usadas para passar metadados personalizados sobre as colunas para o gerador de script de migração.
Usar uma convenção para fazer isso demonstra o poder por trás da notação de atributo para simplificar como os metadados fluentes podem ser definidos e manipulados para muitas propriedades, em vez de especificá-los individualmente para cada campo.
Adicionar a convenção ao DbContext
Há muitas maneiras de conseguir isso. Gosto de declarar as convenções como a primeira etapa personalizada em minha lógica ModelCreation, isso será em sua classe DbContext.
Substituir o MigrationCodeGenerator
Agora que essas anotações foram aplicadas às definições de coluna dentro do modelo, precisamos modificar o gerador de script de migração para usar essas anotações. Para isso, herdaremos do
System.Data.Entity.Migrations.Design.CSharpMigrationCodeGenerator
, pois só precisamos injetar uma quantidade mínima de mudança.Depois de processarmos nossa anotação personalizada, precisamos removê-la da definição de coluna para evitar que seja serializada para a saída final.
Registre o CustomCodeGenerator
Última etapa, no arquivo de configuração DbMigration, precisamos especificar o gerador de código a ser usado, procure Configuration.cs em sua pasta de migração por padrão ...
fonte
Por alguma razão, não fui capaz de me explicar, a resposta aprovada não funciona mais para mim.
Funcionou em outro aplicativo, naquele em que estou trabalhando, não funciona.
Portanto, uma solução alternativa, mas bastante ineficiente , seria sobrescrever o método SaveChanges () conforme mostrado abaixo. Este método deve estar na classe Context.
fonte