Quiero escribir un poco de C# código para inicializar la base de datos con algunas semillas de datos. Claramente, esto va a requerir de la capacidad de ser capaz de establecer los valores de varias columnas de Identidad a la hora de insertar. Estoy usando un código como primer enfoque. De forma predeterminada, DbContext se encarga de la conexión de base de datos y por eso no puede SET IDENTITY_INSERT [dbo].[MyTable] ON. Así, lo que he hecho hasta el momento es el uso de la DbContext constructor que me permite especificar una conexión DB para ser utilizado. Entonces, me puse IDENTITY_INSERT a ON en que la conexión DB, y a continuación, intente insertar mis registros utilizando entity framework. He aquí un ejemplo de lo que he conseguido hasta ahora:

public class MyUserSeeder : IEntitySeeder {
    public void InitializeEntities(AssessmentSystemContext context, SqlConnection connection) {
        context.MyUsers.Add(new MyUser { MyUserId = 106, ConceptPersonId = 520476, Salutation = "Mrs", Firstname = "Novelette", Surname = "Aldred", Email = null, LoginId = "520476", Password="28c923d21b68fdf129b46de949b9f7e0d03f6ced8e9404066f4f3a75e115147489c9f68195c2128e320ca9018cd711df", IsEnabled = true, SpecialRequirements = null });
        try {
            connection.Open();
            SqlCommand cmd = new SqlCommand("SET IDENTITY_INSERT [dbo].[MyUser] ON", connection);
            int retVal = cmd.ExecuteNonQuery();
            context.SaveChanges();
        }
        finally {
            connection.Close();
        }
    }
}

Tan cerca y tan lejos – porque, a pesar de cmd.ExecuteNonQuery() funciona bien, cuando luego de ejecutar context.SaveChanges(), estoy informado de que «valor Explícito debe ser especificado para la columna de identidad en la mesa «Miusuario’ cuando IDENTITY_INSERT está activado o cuando un usuario de replicación es la inserción en un NO PARA la REPLICACIÓN de la columna de identidad.»

Presumiblemente, porque MyUserId (que es la columna de Identidad en el MyUser tabla) es la clave primaria, entity framework no intenta establecer que cuando me llaman context.SaveChanges(), aunque me dio la MyUser entidad un valor para el MyUserId propiedad.

Es allí una manera a la fuerza de entity framework para intentar insertar incluso valores de clave principal de una entidad, entonces? O tal vez una manera de marcar temporalmente MyUserId como no ser un valor de clave principal, así EF intenta insertarlo?

InformationsquelleAutor Jez | 2012-10-26

10 Comentarios

  1. 46

    EF 6 método, utilizando el artículo de msdn:

        using (var dataContext = new DataModelContainer())
        using (var transaction = dataContext.Database.BeginTransaction())
        {
          var user = new User()
          {
            ID = id,
            Name = "John"
          };
    
          dataContext.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [dbo].[User] ON");
    
          dataContext.User.Add(user);
          dataContext.SaveChanges();
    
          dataContext.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [dbo].[User] OFF");
    
          transaction.Commit();
        }

    Actualización: Para evitar el error «valor Explícito debe ser especificado para la columna de identidad de la tabla ‘Nombretabla’ cuando IDENTITY_INSERT está activado o cuando un usuario de replicación es la inserción en un NO PARA la REPLICACIÓN de la columna de identidad», debe cambiar el valor de StoreGeneratedPattern propiedad de columna de identidad de la Identidad a la Ninguno en el diseñador de modelos.

    Nota, el cambio de StoreGeneratedPattern a Ninguno se producirá la inserción de objeto sin id especificado (modo normal) con el error «No se puede insertar un valor explícito para la columna de identidad de la tabla ‘Nombretabla’ cuando IDENTITY_INSERT es OFF».

    • Esto no en todas abordar el tema de la EF no la inserción de la clave, en lugar de que la dirección de cómo hacer transaccional
    • Así, se hace transaccional, pero no resuelve el problema de la identidad de insertar, ¿no?
    • Cuando traté de esto, yo tengo el error: «valor Explícito debe ser especificado para la columna de identidad de la tabla ‘mitabla’ cuando IDENTITY_INSERT está activado o cuando un usuario de replicación es la inserción en un NO PARA la REPLICACIÓN de la columna de identidad.» (Aunque HICE establecer un valor para mi registro de la tabla de la identidad del objeto de campo antes de llamar a la SaveChanges.)
    • Jon, es otro problema, 1er resultado de la búsqueda de google: support.microsoft.com/en-us/kb/908711
    • Gracias por la ayuda! Sin embargo, he comprobado, y el «not For Replication» propiedad en mi columna de identidad se establece en false. Sospecho que el problema es que la EF no está tratando de enviar mi ID especificado valor a la base de datos (como se discutió en la «Actualización» al Doctor Jones’ respuesta).
    • parece envolverlo en una transacción que se requiere para hacer que esto funcione
    • Esto significa que, de repente, el código tiene que tener conocimiento de los nombres de tabla. El punto de Entity Framework es abstracto que información.
    • xr280xr, sí, no es la solución ideal, pero me muestre mejor? 🙂

  2. 18

    Usted no necesita hacer cualquier negocio gracioso con la conexión, se puede reducir al hombre medio y sólo tiene que utilizar ObjectContext.ExecuteStoreCommand.

    Entonces, usted puede lograr lo que desee hacer esto:

    context.ExecuteStoreCommand("SET IDENTITY_INSERT [dbo].[MyUser] ON");

    No sé de ningún incorporado manera de decirle a EF para establecer la identidad de insertar en el aunque.

    No es perfecto, pero sería más flexible y menos «chapucero» de su enfoque actual.

    Actualización:

    Me di cuenta de que hay una segunda parte a su problema. Ahora que has dicho SQL que desea hacer inserciones de identidad, EF no está aún tratando de insertar valores para dicha identidad (¿por qué? no hemos dicho a).

    Yo no tengo ninguna experiencia con un código de primer enfoque, pero a partir de algunas búsquedas rápidas parece que usted necesita decirle a EF que su columna no debe ser generado a partir de la tienda. Tendrás que hacer algo como esto.

    Property(obj => obj.MyUserId)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None)
        .HasColumnName("MyUserId");

    Esperemos que esto le apunta en la dirección correcta 🙂

    • Hmm, que Property código que habría que hacer en OnModelCreating ¿no? No habría alguna manera de indicar que la información de la EF después de OnModelCreating se ha ejecutado?
    • Grandes problemas? No se si fue sólo un derecho cuando inicialmente se ejecutó la aplicación, a la semilla de los datos existentes. También sería muy útil para la rápida configuración de seguridad de bases de datos de desarrollo, en una base de datos independiente de la forma (seguro que usted puede hacer esto con TSQL, pero no estás encerrado en SQL Server).
    • Sí, yo tenía un viernes por la tarde cerebro falla, por lo tanto he quitado mi comentario. Todavía creo que la creación de una entidad especialmente para la realización de su identidad inserta es una opción si usted no puede encontrar una mejor manera de hacerlo. Háganos saber lo que usted viene para arriba con, yo te interese saber!
    • Se puede aplicar el DatabaseGenerationOption condicionalmente. I explicó cómo yo lo hice en mi respuesta.
    • Creo que el problema con el uso de HasDatabaseGeneratedOption(DatabaseGeneratedOption.Ninguno) es que cuando, a continuación, utilizar la aplicación con entity framework, la inserción fallará porque EF espera ahora un ID para ser suministrado con cualquier inserta.
    • El negocio gracioso la que te refieres es la creación de una transacción, que debe considerarse como una parte necesaria de una consulta como esta. Si usted renunciar a la transacción, el resto de llamadas a la base de datos al mismo tiempo que esperar IDENTITY_INSERT a ser va A ser afectado.
    • no. El «negocio gracioso» me refería a que hubo manipulación manual de la conexión de SQL, es decir, lo que sucede en el cuerpo de InitializeEntities de la OP.

  3. 11

    Poco tarde a la fiesta, pero en caso de que alguien se encuentra con este problema en EF5 con DB primero: yo no podía conseguir a cualquier solución para que funcione, pero no encontró otra solución:

    Antes de la ejecución de la .SaveChanges() comando, puedo restablecer la tabla de identidad del contador:

    Entities.Database.ExecuteSqlCommand(String.Format("DBCC CHECKIDENT ([TableNameHere], RESEED, {0})", newObject.Id-1););
    Entities.YourTable.Add(newObject);
    Entities.SaveChanges();

    Esto significa que .SaveChanges() debe ser aplicado después de cada adición – pero al menos funciona!

    • Hey tu solución funciona para la actualización propósito, pero hay un problema que viene ahora en mi lado es que se inicia el primer registro con clave principal 0.
    • Día del ahorro, soluciones para la modificación de las columnas no es ideal, ya que se necesitaría para actualizar un servidor de producción dos veces. Esto funciona perfecto. Sólo ten en cuenta que cuando usted sabe que va a ser de insertar el primer registro, eliminar la -1.
    • ¿Por qué no la primera fila se inserta con el ID correcto?
    • Si la inserción de código, posiblemente, puede ejecutarse simultáneamente (por ejemplo, parte de un sitio web típico), asegúrese de envolver el comando SQL y la fila agregar en una transacción. De lo contrario, en ocasiones, su aplicación va a pensar que el nuevo objeto tiene un IDENTIFICADOR, mientras que SQL Server se ha almacenado una diferente. Las cargas de la diversión para depurar!
    • ¿Cómo envolver los tres comandos anteriores en una transacción cuando el uso de EF?
    • Utilizando el soporte de transacciones construido en EF o EF Core.

  4. 6

    Aquí está la solución del problema. Lo he probado en EF6 y trabajó para mí. Siguiente es el pseudo código que funcione.

    Primer lugar usted necesita para crear la sobrecarga del defecto de dbcontext. Si usted llega a la clase base, usted encontrará el uno con el pasar de los existentes dbConnection.
    Verificación de código siguiente-

    public MyDbContext(DbConnection existingConnection, bool contextOwnsConnection)
            : base(existingConnection, contextOwnsConnection = true)
        {
            //optional
            this.Configuration.ProxyCreationEnabled = true;
            this.Configuration.LazyLoadingEnabled = true;
            this.Database.CommandTimeout = 360;
        }

    Y en modelcreating quitar la base de datos generada opción, como por ejemplo,

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<MyTable>()
                .Property(a => a.Id)
                .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
    
            base.OnModelCreating(modelBuilder);
        }

    Ahora en el código que necesita para pasar un objeto de conexión de forma explícita,

    using (var connection = new System.Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionStringName"].ConnectionString))
            {
                connection.Open();
                using (var context = new MyDbContext(connection, true))
                {
                    context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [dbo].[MyTable] ON");
                    context.MyTable.AddRange(objectList);
                    context.SaveChanges();
                    context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [dbo].[MyTable] OFF");
                }
    
                connection.Close();
            }
  5. 2

    Después de una cuidadosa consideración, he decidido que el marco de la entidad a la negativa de insertar las columnas de identidad es una característica, no un bug. 🙂 Si yo fuera a ser la inserción de todas las entradas en mi base de datos, incluyendo sus valores de identidad, también me tiene que crear una entidad para cada uno de los enlaces de la tabla que entity framework había creado automáticamente para mí! Simplemente no es el enfoque correcto.

    Lo que voy a hacer es configurar la siembra de clases que sólo el uso de código de C# y crear EF entidades, a continuación, utilizar un DbContext para guardar el recién creado de datos. Se tarda un poco más para tomar el objeto de dumping SQL y convertirlo en código de C#, pero no la hay (y no debería ser) el exceso de datos sólo para la «siembra» de datos debe ser una pequeña cantidad de datos que es representante de la clase de datos que sería en un DB que puede ser puesta rápidamente en un nuevo DB para la depuración/fines de desarrollo. Esto significa que si quiero de enlace de entidades juntos, tengo que hacer las consultas en lo que ya se ha insertado o mi código no conocen su valor de identidad generado, por ejemplo. Este tipo de cosas aparecen en la siembra de código, después de que he creado y hecho context.SaveChanges para MyRoles:

    var roleBasic = context.MyRoles.Where(rl => rl.Name == "Basic").First();
    var roleAdmin = context.MyRoles.Where(rl => rl.Name == "Admin").First();
    var roleContentAuthor = context.MyRoles.Where(rl => rl.Name == "ContentAuthor").First();
    
    MyUser thisUser = context.MyUsers.Add(new MyUser {
        Salutation = "Mrs", Firstname = "Novelette", Surname = "Aldred", Email = null, LoginUsername = "naldred", Password="c1c966821b68fdf129c46de949b9f7e0d03f6cad8ea404066f4f3a75e11514748ac9f68695c2128e520ca0275cd711df", IsEnabled = true, SpecialRequirements = null
    });
    thisUser.Roles.Add(roleBasic);

    Haciendo de esta manera también hace que sea más probable es que voy a actualizar mi siembra de datos al cambiar el esquema, porque lo más probable es que rompa la siembra de código cuando lo cambio (si puedo eliminar un campo o una entidad, la siembra de código que utiliza ese campo/entidad error de compilación). Con una secuencia de comandos SQL para realizar la siembra, que no sería el caso, y tampoco sería la secuencia de comandos SQL ser de base de datos independiente.

    Así que creo que si usted está tratando de establecer la identidad de los campos de las entidades para hacer DB siembra de datos, usted ha tomado definitivamente el enfoque equivocado.

    Si yo fuera realmente arrastrar una carga de datos de SQL Server a PostgreSQL (completo en vivo DB, no sólo a algunos de siembra de datos), podría hacerlo a través de la EF, pero me gustaría tener dos contextos abiertos al mismo tiempo, y escribir algo de código para agarrar todas las diversas entidades del contexto de origen de las y los ponemos en el contexto de destino, a continuación, guardar los cambios.

    Por lo general, la única vez que se proceda a insertar los valores de identidad es cuando se van a copiar de una DB a otra base de datos dentro de la misma gestor de base de datos (SQL Server -> SQL Server, PostgreSQL -> PostgreSQL, etc.), y entonces quieres hacerlo en una secuencia de comandos SQL y no EF code-first (la secuencia de comandos SQL no sería DB-agnóstico, pero no necesitan ser; usted no va entre los diferentes Dbms).

    • Hay casos válidos para hacerlo, como importar datos de otro sistema.
  6. 2

    Esta idea sólo funciona de forma fiable si la tabla de destino está vacío, o se insertan registros con id mayor que todos los ya existentes id en la tabla!

    De 3 años y me golpeó un problema similar, la transferencia de los datos de producción en un sistema de prueba. Los usuarios querían ser capaz de copiar los datos de producción en el sistema de prueba cada vez que querían, así que en lugar de la configuración de una transferencia de trabajo en SQL Server me miró de una manera, para lograr la transferencia en la aplicación en las clases de EF. De esta forma, se podría proporcionar a los usuarios una opción de menú para iniciar la transferencia cada vez que querían.

    La aplicación utiliza un Servidor MS SQL server 2008 de la base de datos y EF 6. Como las dos bases de datos en general tienen la misma estructura pensé que podría transferir fácilmente los datos de un DbContext instancia a otra mediante la lectura de los registros de cada entidad, mediante AsNoTracking() y sólo Add() (o AddRange()) los registros de la propiedad correspondiente en el objetivo de DbContext instancia.

    Aquí es un DbContext con una entidad para ilustrar:

    public class MyDataContext: DbContext
    {
        public virtual DbSet<Person> People { get; set; }
    }

    Para copiar los datos de que hice lo siguiente:

    private void CopyPeople()
    {
        var records = _sourceContext.People.AsNoTracking().ToArray();
        _targetContext.People.AddRange(records);
        _targetContext.SaveChanges();
    }

    Mientras que las tablas se han copiado en el orden correcto (para evitar problemas con restricciones de clave externa) esto funcionó muy bien. Por desgracia tablas con columnas de identidad de las cosas un poco difíciles, como EF omite la identificación de los valores y dejar de SQL Server introduzca el siguiente valor de identidad. Para las tablas con columnas de identidad lo que terminó haciendo la siguiente:

    1. Leer todos los registros de una entidad dada
    2. Orden de los registros de identificación en orden ascendente
    3. establecer la identidad de la semilla para que la tabla el valor de la primera id
    4. seguir la pista de la próxima valor de identidad, agregar los registros uno por uno. Si el id no es el mismo que el previsto el próximo valor de identidad establecer la identidad de la semilla para el siguiente valor de

    Siempre y cuando la tabla está vacía (o todos los nuevos registros tienen identificadores mayor que la actual hisghest id), y los identificadores son, en orden ascendente, EF y MS SQL se inserte el id y no se quejan.

    Aquí es un poco de código para ilustrar:

    private void InsertRecords(Person[] people)
    {
        // setup expected id - presumption: empty table therefore 1
        int expectedId = 1;
    
        // now add all people in order of ascending id
        foreach(var person in people.OrderBy(p => p.PersonId))
        {
            // if the current person doesn't have the expected next id
            // we need to reseed the identity column of the table
            if (person.PersonId != expectedId)
            {
                // we need to save changes before changing the seed value
                _targetContext.SaveChanges();
    
                // change identity seed: set to one less than id
                //(SQL Server increments current value and inserts that)
                _targetContext.Database.ExecuteSqlCommand(
                    String.Format("DBCC CHECKIDENT([Person], RESEED, {0}", person.PersonId - 1)
                );
    
                // update the expected id to the new value
                expectedId = person.PersonId;
            }
    
            // now add the person
            _targetContext.People.Add(person);
    
            // bump up the expectedId to the next value
            // Assumption: increment interval is 1
            expectedId++;
        }
    
        // now save any pending changes
        _targetContext.SaveChanges();
    }

    El uso de la reflexión que yo era capaz de escribir una Load y un Save método que funcionó para todas las entidades en el DbContext.

    Es un poco de un hack, pero me permite utilizar el estándar EF métodos para leer y escribir entidades y supera el problema de cómo establecer la identidad de las columnas a los valores particulares bajo un conjunto de circunstancias dadas.

    Espero que esto sea de ayuda para alguien más se enfrentan con un problema similar.

  7. 1

    Después de experimentar varias opciones que se encuentran en este sitio, el código siguiente trabajado para mí (EF 6). Observe que los primeros intentos de una actualización de lo normal si el elemento ya existe. Si no lo hace, entonces se trata de una normal inserción, si el error es debido a IDENTITY_INSERT, a continuación, intenta la solución. Observe también que db.SaveChanges fallará, por lo tanto la base de datos.La base de datos.Conexión.Open() instrucción y verificación opcional paso. Ser consciente de que esto no es la modificación del contexto, pero en mi caso no es necesario. Espero que esto ayude!

    public static bool UpdateLeadTime(int ltId, int ltDays)
    {
    try
    {
    using (var db = new LeadTimeContext())
    {
    var result = db.LeadTimes.SingleOrDefault(l => l.LeadTimeId == ltId);
    if (result != null)
    {
    result.LeadTimeDays = ltDays;
    db.SaveChanges();
    logger.Info("Updated ltId: {0} with ltDays: {1}.", ltId, ltDays);
    }
    else
    {
    LeadTime leadtime = new LeadTime();
    leadtime.LeadTimeId = ltId;
    leadtime.LeadTimeDays = ltDays;
    try
    {
    db.LeadTimes.Add(leadtime);
    db.SaveChanges();
    logger.Info("Inserted ltId: {0} with ltDays: {1}.", ltId, ltDays);
    }
    catch (Exception ex)
    {
    logger.Warn("Error captured in UpdateLeadTime({0},{1}) was caught: {2}.", ltId, ltDays, ex.Message);
    logger.Warn("Inner exception message: {0}", ex.InnerException.InnerException.Message);
    if (ex.InnerException.InnerException.Message.Contains("IDENTITY_INSERT"))
    {
    logger.Warn("Attempting workaround...");
    try
    {
    db.Database.Connection.Open();  // required to update database without db.SaveChanges()
    db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT[dbo].[LeadTime] ON");
    db.Database.ExecuteSqlCommand(
    String.Format("INSERT INTO[dbo].[LeadTime]([LeadTimeId],[LeadTimeDays]) VALUES({0},{1})", ltId, ltDays)
    );
    db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT[dbo].[LeadTime] OFF");
    logger.Info("Inserted ltId: {0} with ltDays: {1}.", ltId, ltDays);
    // No need to save changes, the database has been updated.
    //db.SaveChanges(); <-- causes error
    }
    catch (Exception ex1)
    {
    logger.Warn("Error captured in UpdateLeadTime({0},{1}) was caught: {2}.", ltId, ltDays, ex1.Message);
    logger.Warn("Inner exception message: {0}", ex1.InnerException.InnerException.Message);
    }
    finally
    {
    db.Database.Connection.Close();
    //Verification
    if (ReadLeadTime(ltId) == ltDays)
    {
    logger.Info("Insertion verified. Workaround succeeded.");
    }
    else
    {
    logger.Info("Error!: Insert not verified. Workaround failed.");
    }
    }
    }
    }
    }
    }
    }
    catch (Exception ex)
    {
    logger.Warn("Error in UpdateLeadTime({0},{1}) was caught: {2}.", ltId.ToString(), ltDays.ToString(), ex.Message);
    logger.Warn("Inner exception message: {0}", ex.InnerException.InnerException.Message);
    Console.WriteLine(ex.Message);
    return false;
    }
    return true;
    }
  8. -1

    Yo sólo soy un DBA, pero cada vez que algo como esto aparece, considero que es un código de olor. Es decir, ¿por qué usted tiene algo que depende de ciertas filas tener ciertos valores de identidad? Es decir, en el ejemplo anterior, ¿por qué la Señora Novelette necesita un valor de identidad de 106? En lugar de confiar en que siempre es el caso, usted puede obtener su valor de identidad y el uso de que, dondequiera que usted tendría codificado 106. Un poco más incómodo, pero de manera más flexible (en mi opinon).

    • Porque estoy inicializando los datos de otra base de datos. Es mucho más sencillo de mantener los valores de la identidad a partir de esa base de datos y mantener la clave externa hace referencia a la misma.
    • Los valores de identidad debe ser tratado siempre como arbitraria. Si tienen un valor intrínseco (como parece ser atribuirle a ellos), no hacer que la columna una columna de identidad.
    • Que se aplica en circunstancias normales, pero este es un dato de la siembra con algunos datos específicos. Yo diría que no se aplican en virtud de esta circunstancia especial. De hecho, si se siembra la base de datos a partir de una secuencia de comandos SQL, que sería probable que a su vez IDENTITY_INSERT mientras inserta los datos y especificar la identidad de los valores de campo.
  9. -1

    Es allí una manera a la fuerza de entity framework para intentar insertar incluso valores de clave principal de una entidad?

    Sí, pero no tan limpiamente como me gustaría ver.

    Asumiendo que usted está utilizando una auto-identidad generado clave, EF se ignoran por completo su intento de almacenar el valor de la clave. Este parece ser «Por diseño» por las muchas buenas razones detalladas anteriormente, pero todavía hay veces cuando se desea controlar plenamente su semilla de datos (o una inicial de carga). Sugiero EF accomidate este tipo de siembra en una versión futura. Pero hasta que lo hagan, acaba de escribir un poco de código que funciona en el marco y automatiza los detalles más complejos.

    Eventho VendorID es ignorado por EF, se puede utilizar con básicos de bucle y el conteo para determinar cuántos en lugar del titular de los registros de añadir entre su live records. El lugar de los titulares se les asigna el siguiente número de IDENTIFICACIÓN cuando se agregan. Una vez que su live records han solicitado IDs, sólo se necesita para eliminar la basura.

    public class NewsprintInitializer: DropCreateDatabaseIfModelChanges<NewsprintContext>
    {
    protected override void Seed(NewsprintContext context)
    {
    var vendorSeed = new List<Vendor>
    {
    new Vendor { VendorID = 1, Name = "#1 Papier Masson /James McClaren" },
    new Vendor { VendorID = 5, Name = "#5 Abitibi-Price" },
    new Vendor { VendorID = 6, Name = "#6 Kruger Inc." },
    new Vendor { VendorID = 8, Name = "#8 Tembec" }
    };
    //  Add desired records AND Junk records for gaps in the IDs, because .VendorID is ignored on .Add
    int idx = 1;
    foreach (Vendor currentVendor in vendorSeed)
    {
    while (idx < currentVendor.VendorID)
    {
    context.Vendors.Add(new Vendor { Name = "**Junk**" });
    context.SaveChanges();
    idx++;
    }
    context.Vendors.Add(currentVendor);
    context.SaveChanges();
    idx++;
    }
    //  Cleanup (Query/Find and Remove/delete) the Junk records
    foreach (Vendor del in context.Vendors.Where(v => v.Name == "**Junk**"))
    {
    context.Vendors.Remove(del);
    }
    context.SaveChanges();
    // setup for other classes
    }
    }

    Funcionó como se esperaba, excepto que tenía que hacer «SaveChanges» con frecuencia para mantener el Id de la orden.

  10. -2

    No podía encontrar una manera de insertar registros en una tabla. Básicamente, he creado un script SQL con algo como esto…

                sb.Append("SET IDENTITY_INSERT [dbo].[tblCustomer] ON;");
    foreach(...)
    {
    var insert = string.Format("INSERT INTO [dbo].[tblCustomer]
    ([ID],[GivenName],[FamilyName],[NINumber],[CustomerIdent],
    [InputterID],[CompanyId],[Discriminator]) 
    VALUES({0}, '{1}', '{2}', '{3}', '{4}', 2, 2, 'tblCustomer'); ", 
    customerId, firstName, surname, nINumber, Guid.NewGuid());
    sb.Append(insert);
    ...
    }
    sb.Append("SET IDENTITY_INSERT [dbo].[tblCustomer] OFF;");
    using (var sqlConnection = new SqlConnection(connectionString))
    {
    var svrConnection = new ServerConnection(sqlConnection);
    var server = new Server(svrConnection);
    server.ConnectionContext.ExecuteNonQuery(sb.ToString());
    }

    Estoy usando EF 6.

    • Esto es bastante horrible y es vulnerable a Inyección SQL – por favor, no hagas como este, no nunca!
    • Estoy de acuerdo en su horrible pero yo sólo lo uso cuando se siembra la DB no en código en vivo, por lo que la Inyección de SQL no es un problema.
    • Esta es casi la única cosa que funciona. Inserción Manual. Debe proteger contra ataques de inyección SQL, pero es el enfoque correcto, ya que la EF es insufrible.

Dejar respuesta

Please enter your comment!
Please enter your name here