2012-06-03 15 views
24

Al agregar una nueva columna no anulable a una tabla mediante el uso de las primeras migraciones de código, creará automáticamente un valor predeterminado para usted. Esto tiene sentido porque las filas existentes deben tener un valor para la nueva columna (ya que no puede ser nulo). Está bien, pero después de que ese valor se asigna en todas partes, ya no lo quiero más. No admite nulos, porque quiero asegurarme de que siempre se inserte explícitamente un valor. Si todo está predeterminado en '' o 0, tendré cadenas mágicas. De todos modos, puedo levantar una solución, que no me entusiasma, pero funciona.Eliminación de una restricción predeterminada después de agregar una nueva columna en el código primero

Después de agregar la columna, elimino la restricción predeterminada.

public override void Up() 
{ 
    AddColumn("dbo.SomeTable", "NewColumn", c => c.Int(nullable: false)); 
    Sql(Helpers.DropDefaultConstraint("dbo.SomeTable", "NewColumn")); 
} 

...

public static string DropDefaultConstraint(string table, string column) 
{ 
    return string.Format(@" 
     DECLARE @name sysname 

     SELECT @name = dc.name 
     FROM sys.columns c 
     JOIN sys.default_constraints dc ON dc.object_id = c.default_object_id 
     WHERE c.object_id = OBJECT_ID('{0}') 
     AND c.name = '{1}' 

     IF @name IS NOT NULL 
      EXECUTE ('ALTER TABLE {0} DROP CONSTRAINT ' + @name) 
     ", 
     table, column); 
} 

PROS: Una vez implementado el método de ayuda, sólo hay que añadir una línea simple de quitar la restricción. CONS: Parece innecesario crear un índice solo para eliminarlo.

Otro enfoque sería alterar la migración generada, por lo que agregamos que tiene valores de nulos, actualiza todos los valores y luego no puede contener nulos.

public override void Up() 
{ 
    AddColumn("dbo.SomeTable", "NewColumn", c => c.Int()); 
    Sql("UPDATE dbo.SomeTableSET NewColumn= 1"); 
    AlterColumn("dbo.SomeTable", "NewColumn", c => c.Int(nullable: false)); 
} 

PROS: parece más sencillo/limpiador

CONS: tener que alterar mis limitaciones temporalmente (I asumir esta se ejecuta en una transacción y por lo tanto no se debe permitir que los malos datos in). La actualización puede ser lenta en las tablas grandes.

¿Qué método es preferible? ¿O hay una mejor manera en la que me estoy perdiendo?

Nota: He demostrado el caso en el que está agregando y limpiando definiciones de columna de una vez. Si solo está limpiando los valores predeterminados de migraciones anteriores, el segundo enfoque no es útil.

+2

La solución 1 me ayudó a eliminar una restricción predeterminada, gracias. – angularsen

+0

esto es impresionante –

Respuesta

10

Personalmente, no puedo ver nada malo con el primer acercamiento. Sí, debe crear una restricción predeterminada para agregar una columna que no admite nulos a un conjunto de datos no vacío. Y sí, tiene que eliminarlo luego si necesita asegurarse de que la nueva columna siempre se agregue explícitamente en el futuro, según su requisito.

E incluso si todavía tiene problemas con este enfoque, el problema es que probablemente no haya otra alternativa aparte de su segundo enfoque. Y el costo de actualizar una tabla posiblemente grande con un valor predeterminado me parecería mayor que el costo de crear y eliminar inmediatamente una restricción predeterminada.

me podría considerar una ligera modificación, sin embargo: podría crear la restricción en SQL para evitar el alboroto de buscar un nombre predeterminado asignado por el motor, algo como esto:

Sql("ALTER TABLE tablename 
    ADD columnnametype NOT NULL 
    CONSTRAINT DF_tablename_columnname DEFAULT defaultvalue"); 

(podría reescribirse utilizar una función auxiliar)

eliminar una restricción sería entonces tan trivial como la ejecución de una sola sentencia ALTER TABLE:.

Sql("ALTER TABLE tablename 
    DROP CONSTRAINT DF_tablename_columnname"); 

(una vez más, una la función auxiliar se puede usar fácilmente aquí.)

Pero eso podría ser un desarrollador de T-SQL en mí hablando más fuerte que un C#.Por lo que es muy probable que vaya con el código como el ejemplo que ha publicado.

+0

Gracias por validar mis pensamientos. Consideré crear la restricción yo mismo, pero prefiero usar AddColumn ya que es fácil y consistente de leer y también permite otras restricciones, como únicas. Decidí seguir con la opción 1. Gracias. –

Cuestiones relacionadas