Tengo una tabla que almacena algunos datos adicionales para algunas filas de una tabla como:

public class QuoteExtra
{
    [Key]
    public int QuoteId { get; set; }
    //More fields here
}

Me gustaría ser capaz de añadir filas a la tabla donde puedo establecer explícitamente el PK.

Si yo simplemente dejarlo como en el anterior, el establecimiento de un valor y la presentación de las causas de la fila el valor a ser desechado y sustituido por el valor generado automáticamente a partir de la base de datos (y la columna se define como una columna de Identidad en el esquema real).

Esta parece ser la solución correcta:

public class QuoteExtra
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int QuoteId { get; set; }
    //More fields here
}

Sin embargo, este lugar me pone la excepción:

No se puede insertar un valor explícito para la columna de identidad de la tabla ‘EnumTest’ cuando IDENTITY_INSERT es OFF.

Así que, ¿cómo escribo mi clase, así que soy capaz de establecer el valor de una Clave Principal en EF?

Edición:

He intentado añadir el siguiente Código basado en la Migración a set IDENTITY_INSERT EN:

public override void Up()
{
    Sql("SET IDENTITY_INSERT QuoteExtra ON");
}

Lo corrió y lo intentó de nuevo, pero tengo la misma salvedad anterior. Lo extraño es que la base de datos no reflejan esta configuración, y que ejecuta SQL contra él directamente no me permite insertar valores arbitrarios para la clave primaria – por lo que parece Entity Framework en sí es la aplicación de esta regla, y dejar de lado a reconocer que IDENTITY_INSERT de hecho no está ajustado a off. Necesito configurar en alguna parte en EF sí mismo?

Edit 2:

He entendido IDENTITY_INSERT; supuse configuración una vez a la izquierda en la tabla de forma indefinida. De hecho, es la vida mientras la «Sesión», lo que significa que para la configuración de ejemplo que en una Migración que se vive… como que la Migración se ejecuta, y no tiene influencia en las futuras conexiones como en mi posterior .Agregar() con EF, lo que explica por qué todavía tengo esa excepción – el DB es realmente la fuente de la excepción, no la EF. Desde IDENTITY_INSERT está limitado a un máximo de una tabla por sesión es bastante ineficiente para hacer esto – no la creación de una Identidad PK columna, en primer lugar, parece una ruta mejor.

  • ¿A qué te refieres por Lo que es extraño es la base de datos no reflejan esta configuración?
  • A lo que me refería era que yo era capaz de insertar valores si he utilizado raw SQL para hacerlo después de la ejecución de la identity_insert en el comando – pero ahora veo por qué – es porque el valor es por la duración de una sesión, y en raw SQL en Sql Server Management Studio me quedé dentro de la duración de una sesión, mientras que mi EF migración y siguientes del código de pruebas son independientes de las sesiones.
  • Sí. La inserción de identidad es relativa a la conexión. Si usted asegurarse de que su código se ejecuta en dentro de la misma conexión debe ser capaz de utilizarlo. Pero de alguna manera es la magia negra, especialmente al considerar las migraciones.

3 Comentarios

  1. 34

    Esta es la forma correcta de crear un PK sin Identidad Autoincrement habilitado:

    public class QuoteExtra
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int QuoteId { get; set; }
        //More fields here
    }

    Sin embargo, si se agrega DatabaseGenerated(DatabaseGeneratedOption.Ninguno)] después de EF Migraciones ya ha creado la tabla, que en silencio no sirve de nada para la tabla. Si este es el escenario que usted necesita para agregar una migración manual para colocar la tabla:

    add-migration RecreateQuoteExtra

    Y en la migración:

    public override void Up()
    {
        DropTable("QuoteExtra");
    }

    EF Automática de las Migraciones, a continuación, automáticamente volver a crear la tabla sin la restricción de Identidad, que le permitirá establecer el valor PK en cualquier momento, sin tener que ejecutar cualquiera de los comandos especiales, como IDENTITY_INSERT EN.

    Suena como una forma menos destructiva forma de hacer esto es que viene en EF7 («Datos en Movimiento»), o usted podría escribir un montón de manual de sql a sí mismo en la migración para crear tablas temporales y mover datos si quería evitar la pérdida de datos existentes en la tabla.

    EDICIÓN: Dependiendo del escenario EF Migraciones no podría volver a crear la tabla – si la clase ya existe y ya está añadido a su DbContext se acaba de caer y salir de él en que, en el sentido de su manual de la migración no sólo tiene que soltar, sino también de crear la tabla. No es un gran problema ya que el andamiaje código EF Migraciones genera a partir de agregar a la migración creará estas declaraciones para usted, pero es un poco más de código para comprobar más problemas.

    • Esto funcionó muy bien para mí. Gracias.
  2. 4

    Es la solución de la derecha, pero sólo para una tabla nueva. Si usted cambia de base de datos generada opción para una tabla existente, EF migraciones no son capaces de realizar este cambio y su QuoteId columna está marcado como Identity en la base de datos.

    • Los documentos en IDENTITY_INSERT especificar esta limitación no, y de hecho en raw SQL puedo activar o desactivar libremente de largo después de que la tabla ha sido creada y especificar los valores de los PK. msdn.microsoft.com/en-us/library/ms188059.aspx Que estado allí en más de una tabla puede tener esta habilitado por sesión, lo que significa que en realidad se necesita para activar no a través de una Migración, sino más bien a la derecha antes de INSERTAR, a continuación, volver a salir, lo cual es bastante feo. Parece que encontrar una manera de desactivar la Identidad funcionalidad sería mejor… .
    • EF no proporciona un método directo para jugar con IDENTITY_INSERT configuración. Mi respuesta original dirigido su juego con DatabaseGeneratedOption.
    • Puedo ver lo que estaba tratando de decir ahora. EF Migraciones tiene que colocar la tabla en orden a realizar este cambio, esto puede ser una limitación de SQL Server.
    • El SQL server realmente necesita para quitar la columna, pero al final puede ser el mismo.
  3. 1

    Yo me cansaría de resolver este Problema con sus Sugerencias, a continuación, he tratado de volver a crear toda la Base de datos pero no estaba funcionando.

    Para solucionar esto, usted tiene que quitar la identidad: true de la propiedad en el primero(!) la creación de la Columna (por ejemplo, Inicial de la Migración).

    Tal vez pueda ayudar a alguien..

    • Sí, eso es lo que mi respuesta dice.
    • El escenario es un poco más complicado ya que me imaginé. Cuando automáticas migraciones están encendidos, es suficiente para tener una (probablemente alterado) modelo con DatabaseGeneratedOption.Ninguno de conjunto en la columna de clave principal, ESTABLECER la IDENTIDAD de INSERTAR EN la tabla en una transacción. Sin embargo, cuando una migración manual se genera mediante código, en primera aproximación, la migración va a tener la identidad: los verdaderos atributos de las columnas de clave principal. Que el establecimiento no está establecido por la migración automática, por lo que debe ser eliminado de la migración Arriba() método antes de crear la base de datos.

Dejar respuesta

Please enter your comment!
Please enter your name here