Agregué la [Required]
anotación de datos a uno de mis modelos en una aplicación ASP.NET MVC . Después de crear una migración, ejecutar el Update-Database
comando da como resultado el siguiente error:
No se puede insertar el valor NULL en la columna 'Director', tabla 'MOVIES_cf7bad808fa94f89afa2e5dae1161e78.dbo.Movies'; la columna no permite valores nulos. ACTUALIZAR falla. La instrucción se ha terminado.
Esto se debe a que algunos registros tienen NULL en sus Director
columnas. ¿Cómo puedo cambiar automáticamente esos valores a algún director predeterminado (por ejemplo, "John Doe")?
Aquí está mi 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; }
}
y aquí está mi última migración:
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());
}
}
fuente
IS NULL
verificación de su consulta."'John Doe'"
- necesitas usar comillas SQL.AlterColumn
actualizaría los valores actuales? Es un comando DDL (no DML).Además de la respuesta de @webdeveloper y @Pushpendra, debe agregar actualizaciones manualmente a su migración para actualizar las filas existentes. Por ejemplo:
Esto se debe a que
AlterColumn
produce DDL para establecer el valor predeterminado de la columna en algún valor específico en la especificación de la tabla. El DDL no afecta las filas existentes en la base de datos.En realidad, está realizando dos cambios al mismo tiempo (estableciendo el valor predeterminado y haciendo que la columna NO sea NULL) y cada uno de ellos es válido individualmente, pero como está haciendo los dos al mismo tiempo, puede esperar que el sistema ' de forma inteligente 'darse cuenta de su intención y establecer todos los
NULL
valores en el valor predeterminado, pero esto no es lo que se espera todo el tiempo.Suponga que solo establece el valor predeterminado para la columna y no lo convierte en NO NULO. Obviamente, no espera que todos los registros NULL se actualicen con el valor predeterminado que proporciona.
Entonces, en mi opinión, esto no es un error, y no quiero que EF actualice mis datos de la manera en que no le digo explícitamente que lo haga. El desarrollador es responsable de instruir al sistema sobre qué hacer con los datos.
fuente
fuente
No estoy seguro de si esta opción siempre estuvo disponible, pero encontré un problema similar, descubrí que pude establecer el valor predeterminado sin ejecutar ninguna actualización manual usando lo siguiente
defaultValueSql: "'NY'"
Recibí un error cuando el valor proporcionado fue
"NY"
entonces me di cuenta de que estaban esperando un valor de SQL como"GETDATE()"
así lo intenté"'NY'"
y eso funcionótoda la línea se ve así
AddColumn("TABLE_NAME", "State", c => c.String(maxLength: 2, nullable: false, defaultValueSql: "'NY'"));
Gracias a esta respuesta , me encaminó por el camino correcto
fuente
Descubrí que solo usar Auto-Property Initializer en la propiedad de la entidad es suficiente para hacer el trabajo.
Por ejemplo:
fuente
Muchas de las otras respuestas se centran en cómo intervenir manualmente cuando ocurren estos problemas.
Tenga en cuenta que los cambios manuales aplicados a una secuencia de comandos de migración se sobrescribirán si reestructura la migración. Para la primera solución, es bastante fácil extender EF para definir un valor predeterminado en un campo automáticamente como parte de la generación de migración.
La siguiente solución combina la notación de atributos, las convenciones de configuración del modelo y las anotaciones de columna para pasar los metadatos a un generador de código de migración personalizado. Los pasos 1 y 2 se pueden reemplazar con notación fluida para cada campo afectado si no está utilizando la notación de atributos.
Hay muchas técnicas en juego aquí, siéntete libre de usar algunas o todas, espero que haya valor para todos aquí.
Declarar el valor predeterminado
Cree o reutilice un atributo existente para definir el valor predeterminado que se utilizará, para este ejemplo crearemos un nuevo atributo llamado DefaultValue que hereda de ComponentModel.DefaultValueAttribute, ya que el uso es intuitivo y existe la posibilidad de que exista las bases de código ya implementan este atributo. Con esta implementación, solo necesita usar este atributo específico para acceder a DefaultValueSql, que es útil para fechas y otros escenarios personalizados.
Implementación
Definición de atributo
Cree una convención para inyectar el valor predeterminado en las anotaciones de columna Las anotaciones de
columna se utilizan para pasar metadatos personalizados sobre columnas al generador de secuencias de comandos de migración.
El uso de una convención para hacer esto demuestra el poder detrás de la notación de atributos para simplificar cómo se pueden definir y manipular metadatos fluidos para muchas propiedades en lugar de especificarlos individualmente para cada campo.
Agregue la convención al DbContext
Hay muchas formas de lograr esto, me gusta declarar las convenciones como el primer paso personalizado en mi lógica ModelCreation, esto estará en su clase DbContext.
Reemplazar el
generador de código de migración Ahora que esas anotaciones se han aplicado a las definiciones de columna dentro del modelo, debemos modificar el generador de secuencias de comandos de migración para usar esas anotaciones. Para esto, heredaremos del
System.Data.Entity.Migrations.Design.CSharpMigrationCodeGenerator
ya que solo necesitamos inyectar una cantidad mínima de cambio.Una vez que hayamos procesado nuestra anotación personalizada, debemos eliminarla de la definición de columna para evitar que se serialice en la salida final.
Registre el CustomCodeGenerator
Último paso, en el archivo de configuración de DbMigration necesitamos especificar el generador de código a usar, busque Configuration.cs en su carpeta de migración por defecto ...
fuente
Desde EF Core 2.1, puede usar
MigrationBuilder.UpdateData
para cambiar valores antes de alterar la columna (más limpio que usar SQL sin formato):fuente
Por alguna razón, que no pude explicarme, la respuesta aprobada ya no me funciona.
Funcionó en otra aplicación, en la que estoy trabajando, no.
Por lo tanto, una solución alternativa, pero bastante ineficiente , sería anular el método SaveChanges () como se muestra a continuación. Este método debe estar en la clase Context.
fuente