2012-09-17 21 views
69

He agregado la anotación de datos [Required] a uno de mis modelos en un ASP.NET MVC application. Después de la creación de una migración, corriendo los Update-Database resultados de los comandos en el siguiente error:Valor predeterminado para los campos obligatorios en las migraciones de Entity Framework?

Cannot insert the value NULL into column 'Director', table 'MOVIES_cf7bad808fa94f89afa2e5dae1161e78.dbo.Movies'; column does not allow nulls. UPDATE fails. The statement has been terminated.

Esto se debe a algunos registros que tienen NULL en sus Director columnas. ¿Cómo puedo cambiar automáticamente esos valores a algún director predeterminado (por ejemplo, "John Doe")?

Aquí es 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()); 
    } 
} 

Respuesta

52

Si no recuerdo mal, algo como esto debería funcionar:

AlterColumn("dbo.Movies", "Director", c => c.String(nullable: false, defaultValueSql: "John Doe")); 
+7

Yo pensaba lo mismo, pero eso no parece trabajo para los registros existentes. Entonces sigo recibiendo un error. – drozzy

+0

@drozzy Tal vez sea un error, como aquí: [EF 4.3.1 Excepción de migración - AlterColumn defaultValueSql crea el mismo nombre de restricción predeterminado para diferentes tablas] (http://stackoverflow.com/questions/9830216/ef-4-3-1 -migration-exception-altercolumn-defaultvaluesql-creates-same-default /) Puede actualizar las filas con la verificación 'IS NULL' por su consulta. – webdeveloper

+0

Interesante, pero no estoy seguro de entender de lo que están hablando. Sin embargo, si esto es un error, entonces sí, tendría sentido. – drozzy

9
public partial class AddDataAnnotationsMig : DbMigration 
{ 
    public override void Up() 
    { 
     AlterColumn("dbo.Movies", "Title", c => c.String(nullable: false,defaultValue:"MyTitle")); 
     AlterColumn("dbo.Movies", "Genre", c => c.String(nullable: false,defaultValue:"Genre")); 
     AlterColumn("dbo.Movies", "Rating", c => c.String(maxLength: 5)); 
     AlterColumn("dbo.Movies", "Director", c => c.String(nullable: false,defaultValue:"Director")); 

    } 

    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());  
    } 
} 
+2

Um ... gracias, pero ¿cómo es eso diferente de la respuesta de @ webdeveloper? – drozzy

+1

no te dice dónde tienes que agregar el parámetro de valor predeterminado – Pushpendra

+1

@Pushpendra, es curioso cómo los desarrolladores tienden a olvidar que alguna vez no sabían mucho. Me gustan las respuestas detalladas que satisfacen todos los niveles. ¡Excelente trabajo! – usefulBee

92

Además de la respuesta de @webdeveloper y @Pushpen dra, necesita agregar manualmente actualizaciones a su migración para actualizar las filas existentes. Por ejemplo:

public override void Up() 
{ 
    Sql("UPDATE [dbo].[Movies] SET Title = 'No Title' WHERE Title IS NULL"); 
    AlterColumn("dbo.Movies", "Title", c => c.String(nullable: false,defaultValue:"MyTitle")); 
} 

Esto es porque AlterColumn produce DDL para establecer el valor predeterminado de la columna a un valor específico en la especificación de tabla. El DDL no afecta las filas existentes en la base de datos.

En realidad, está haciendo dos cambios al mismo tiempo (estableciendo el valor predeterminado y haciendo que la columna NO sea NULA) y cada uno de ellos es válido individualmente, pero ya que está haciendo los dos al mismo tiempo, puede esperar el sistema realiza su intención 'inteligentemente' y establece todos los valores NULL en el valor predeterminado, pero esto no es lo que se espera todo el tiempo.

Supongamos que solo está configurando el valor predeterminado para la columna y no la convierte en NOT NULL. Obviamente, no esperas que todos los registros NULL se actualicen con el valor predeterminado que proporciones.

Por lo tanto, en mi opinión, esto no es un error, y no quiero que EF actualice mis datos en las formas en que no le digo explícitamente que lo haga. El desarrollador es responsable de instruir al sistema sobre qué hacer con los datos.

+11

Para las personas que encuentran esta respuesta a través de google: Acabo de probar esto en EF6 y la declaración de actualización no parece ser necesaria (nunca más). Supongo que lo consideraron un error después de todo. – EPLKleijntjens

+1

También puedo responder por eso. Si necesita un valor predeterminado incluso para un campo que admite valores NULL, simplemente cámbielo primero a no anulable con un valor predeterminado y luego cámbielo a NULL. Muy útil para cuando agregaste un campo que no admite nulos a una clase secundaria :) –

+1

Spot on explanation. AlterColumn() solo altera la definición de la columna. No afecta los registros existentes en absoluto – Korayem

5

no está seguro de si esta opción era siempre alrededor pero sólo se encontró con un problema similar, encontró que yo era capaz de establecer el valor predeterminado sin ejecutar las actualizaciones manuales utilizando la siguiente

defaultValueSql: "'NY'"

Tengo una de error cuando el valor proporcionado era "NY" entonces me di cuenta de que están esperando un valor de SQL como "GETDATE()" así que intentó "'NY'" y que hizo el truco

toda la línea tiene este aspecto

AddColumn("TABLE_NAME", "State", c => c.String(maxLength: 2, nullable: false, defaultValueSql: "'NY'"));

Gracias a this answer, me consiguió en el camino correcto

1

encontré que simplemente usando Auto-Propiedad inicializador en la propiedad de la entidad es suficiente para hacer el trabajo.

Por ejemplo:

public class Thing { 
    public bool IsBigThing { get; set; } = false; 
} 
+0

Es una buena respuesta (me ayudó), pero esto no agrega un valor predeterminado en la base de datos, sino que establece el valor en el código. – chris31389

Cuestiones relacionadas