There are basically 2 different ways to INSERT records without having an error:
1) When the IDENTITY_INSERT is set OFF. The PRIMARY KEY «ID» MUST NOT BE PRESENT
2) When the IDENTITY_INSERT is set ON. The PRIMARY KEY «ID» MUST BE PRESENT
As per the following example from the same Table created with an IDENTITY PRIMARY KEY:
CREATE TABLE [dbo].[Persons] (
ID INT IDENTITY(1,1) PRIMARY KEY,
LastName VARCHAR(40) NOT NULL,
FirstName VARCHAR(40)
);
1) In the first example, you can insert new records into the table without getting an error when the IDENTITY_INSERT is OFF. The PRIMARY KEY «ID» MUST NOT BE PRESENT from the «INSERT INTO» Statements and a unique ID value will be added automatically:. If the ID is present from the INSERT in this case, you will get the error «Cannot insert explicit value for identify column in table…»
SET IDENTITY_INSERT [dbo].[Persons] OFF;
INSERT INTO [dbo].[Persons] (FirstName,LastName)
VALUES ('JANE','DOE');
INSERT INTO Persons (FirstName,LastName)
VALUES ('JOE','BROWN');
OUTPUT of TABLE [dbo].[Persons] will be:
ID LastName FirstName
1 DOE Jane
2 BROWN JOE
2) In the Second example, you can insert new records into the table without getting an error when the IDENTITY_INSERT is ON. The PRIMARY KEY «ID» MUST BE PRESENT from the «INSERT INTO» Statements as long as the ID value does not already exist: If the ID is NOT present from the INSERT in this case, you will get the error «Explicit value must be specified for identity column table…»
SET IDENTITY_INSERT [dbo].[Persons] ON;
INSERT INTO [dbo].[Persons] (ID,FirstName,LastName)
VALUES (5,'JOHN','WHITE');
INSERT INTO [dbo].[Persons] (ID,FirstName,LastName)
VALUES (3,'JACK','BLACK');
OUTPUT of TABLE [dbo].[Persons] will be:
ID LastName FirstName
1 DOE Jane
2 BROWN JOE
3 BLACK JACK
5 WHITE JOHN
There are basically 2 different ways to INSERT records without having an error:
1) When the IDENTITY_INSERT is set OFF. The PRIMARY KEY «ID» MUST NOT BE PRESENT
2) When the IDENTITY_INSERT is set ON. The PRIMARY KEY «ID» MUST BE PRESENT
As per the following example from the same Table created with an IDENTITY PRIMARY KEY:
CREATE TABLE [dbo].[Persons] (
ID INT IDENTITY(1,1) PRIMARY KEY,
LastName VARCHAR(40) NOT NULL,
FirstName VARCHAR(40)
);
1) In the first example, you can insert new records into the table without getting an error when the IDENTITY_INSERT is OFF. The PRIMARY KEY «ID» MUST NOT BE PRESENT from the «INSERT INTO» Statements and a unique ID value will be added automatically:. If the ID is present from the INSERT in this case, you will get the error «Cannot insert explicit value for identify column in table…»
SET IDENTITY_INSERT [dbo].[Persons] OFF;
INSERT INTO [dbo].[Persons] (FirstName,LastName)
VALUES ('JANE','DOE');
INSERT INTO Persons (FirstName,LastName)
VALUES ('JOE','BROWN');
OUTPUT of TABLE [dbo].[Persons] will be:
ID LastName FirstName
1 DOE Jane
2 BROWN JOE
2) In the Second example, you can insert new records into the table without getting an error when the IDENTITY_INSERT is ON. The PRIMARY KEY «ID» MUST BE PRESENT from the «INSERT INTO» Statements as long as the ID value does not already exist: If the ID is NOT present from the INSERT in this case, you will get the error «Explicit value must be specified for identity column table…»
SET IDENTITY_INSERT [dbo].[Persons] ON;
INSERT INTO [dbo].[Persons] (ID,FirstName,LastName)
VALUES (5,'JOHN','WHITE');
INSERT INTO [dbo].[Persons] (ID,FirstName,LastName)
VALUES (3,'JACK','BLACK');
OUTPUT of TABLE [dbo].[Persons] will be:
ID LastName FirstName
1 DOE Jane
2 BROWN JOE
3 BLACK JACK
5 WHITE JOHN
There are basically 2 different ways to INSERT records without having an error:
1) When the IDENTITY_INSERT is set OFF. The PRIMARY KEY «ID» MUST NOT BE PRESENT
2) When the IDENTITY_INSERT is set ON. The PRIMARY KEY «ID» MUST BE PRESENT
As per the following example from the same Table created with an IDENTITY PRIMARY KEY:
CREATE TABLE [dbo].[Persons] (
ID INT IDENTITY(1,1) PRIMARY KEY,
LastName VARCHAR(40) NOT NULL,
FirstName VARCHAR(40)
);
1) In the first example, you can insert new records into the table without getting an error when the IDENTITY_INSERT is OFF. The PRIMARY KEY «ID» MUST NOT BE PRESENT from the «INSERT INTO» Statements and a unique ID value will be added automatically:. If the ID is present from the INSERT in this case, you will get the error «Cannot insert explicit value for identify column in table…»
SET IDENTITY_INSERT [dbo].[Persons] OFF;
INSERT INTO [dbo].[Persons] (FirstName,LastName)
VALUES ('JANE','DOE');
INSERT INTO Persons (FirstName,LastName)
VALUES ('JOE','BROWN');
OUTPUT of TABLE [dbo].[Persons] will be:
ID LastName FirstName
1 DOE Jane
2 BROWN JOE
2) In the Second example, you can insert new records into the table without getting an error when the IDENTITY_INSERT is ON. The PRIMARY KEY «ID» MUST BE PRESENT from the «INSERT INTO» Statements as long as the ID value does not already exist: If the ID is NOT present from the INSERT in this case, you will get the error «Explicit value must be specified for identity column table…»
SET IDENTITY_INSERT [dbo].[Persons] ON;
INSERT INTO [dbo].[Persons] (ID,FirstName,LastName)
VALUES (5,'JOHN','WHITE');
INSERT INTO [dbo].[Persons] (ID,FirstName,LastName)
VALUES (3,'JACK','BLACK');
OUTPUT of TABLE [dbo].[Persons] will be:
ID LastName FirstName
1 DOE Jane
2 BROWN JOE
3 BLACK JACK
5 WHITE JOHN
Working with EF Core 5.0.0-rc2.20475.6, migrated an old EF 6 .NET project.
I used the scaffolding command to generate the models, it worked and a part of the models are like the following example:
public class Betrieb {
public virtual ICollection<Tagesinkassos> Tagesinkassi { get; set; }
// many other properties and collections
}
public class Tagesinkassos {
public long Id { get; set; }
// other properties
public virtual TagesinkassosTagesinkasso TagesinkassosTagesinkasso { get; set; }
public virtual TagesinkassosPostagesinkasso TagesinkassosPostagesinkasso { get; set; }
public virtual Betrieb Betrieb { get; set; }
}
public class TagesinkassosPostagesinkasso {
public long Id { get; set; }
// other properties
public virtual Tagesinkassos IdNavigation { get; set; }
}
public class TagesinkassosTagesinkasso {
public long Id { get; set; }
// other properties
public virtual Tagesinkassos IdNavigation { get; set; }
}
I moved to EF Core 5 because of the TPT, I edited the models followings
public abstract class Tagesinkassos {
public long Id { get; set; }
// other properties
public virtual Betrieb Betrieb { get; set; }
}
public class TagesinkassosPostagesinkasso : Tagesinkassos {
// other properties
}
public class TagesinkassosTagesinkasso : Tagesinkassos {
// other properties
}
Loading data always works.
Update items already present in the Betrieb.Tagesinkassi collection also always works.
If I try to insert a new one, I get the error in the title Cannot insert explicit value for identity column in table 'Tagesinkassos' when IDENTITY_INSERT is set to OFF
I checked the database. The column Tagesinkassos.Id has the Identity Specifcation set to YES. The ids of TagesinkassosPostagesinkasso and TagesinkassosTagesinkasso have the Identity Specifcation set to NO.
Tryied to change from ON to OFF or viceversa, but it tells me that the tables have to de dropped and recreated, I can’t do it.
Is there a way to use the TPT model or do I have to keep the generated one?
If you try to insert in to a table with an ID column, you could get this error “Cannot insert explicit value for identity column in table ‘<<table>>’ when IDENTITY_INSERT is set to OFF.” This is not the end of the world and is actually pretty easy to get around.
Why Are You Getting This Error?
The reason you’re getting this error is because you are trying to tell SQL Server what the ID value for a row in the table should be. If you have an identity column on your table, SQL Server will want to generate that ID value for you automatically. The error is essentially saying, “Hey, I’m supposed to generate the ID for you… you aren’t supposed to tell me what it is!”
How Can You Fix This?
There are two easy ways to get around this.
If You Want To Tell SQL Server What The ID Value Should Be
If want to specify what the ID values should be for the records you are inserting, then before you execute the INSERT statement, you need to run a small sql command to turn identity inserts on. Identity inserts allow you to populate the value of an identity column with a specific value.
|
SET IDENTITY_INSERT Animal ON INSERT INTO Animal (AnimalID, AnimalName) VALUES (1, ‘Horse’), (2, ‘Pig’), (3, ‘Cow’) SET IDENTITY_INSERT Animal OFF |
NOTE: You can only have identity insert on for one table at a time. To insert in to a second table, you will need to turn the identity insert off on the first table before inserting in to the second table.
If You Want To Allow SQL Server To Generate The ID
If you don’t care about what the ID values are for these records, you should just allow SQL Server to generate the ID values for you. To do this, just specify the columns that are in the table and leave off the identity column.
|
INSERT INTO Animal (AnimalName) VALUES (‘Horse’), (‘Pig’), (‘Cow’) |
Reference: http://msdn.microsoft.com/en-us/library/ms188059.aspx
When you have a table with an identity column, and you try to specify the value for identity column when inserting a record, you’ll get the following exception:
Microsoft.Data.SqlClient.SqlException (0x80131904): Cannot insert explicit value for identity column in table ‘Movies’ when IDENTITY_INSERT is set to OFF.
This error means you have an identity column in the table, and you’re trying to set a value for it. When you have an identity column like this, its value gets automatically generated when you insert it, hence why you are prevented from passing in a value for this column.
For example, let’s say your table has the following definition:
Code language: SQL (Structured Query Language) (sql)
CREATE TABLE [dbo].[Movies]( [Id] [int] IDENTITY(1,1) NOT NULL, [Name] [nvarchar](500) NOT NULL, [YearOfRelease] [int] NOT NULL, [Description] [nvarchar](500) NOT NULL, [Director] [nvarchar](100) NOT NULL, [BoxOfficeRevenue] [decimal](18, 2) NOT NULL, CONSTRAINT [PK_Movies] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]
I’ll show a few different solutions for fixing this problem.
Note: The solutions below are showing code examples using EF Core. If you’re using ADO.NET or a different ORM (like Dapper), then the same solutions would work too (just with different code).
Option 1 – Don’t specify the identity column when inserting
The first option is the simplest – don’t try to set the value for the identity column:
Code language: C# (cs)
using (var context = new StreamingServiceContext(connectionString)) { context.Movies.Add(new Movie() { //Id = 20, Name = "Godzilla", Description = "Nuclear lizard fights monsters", Director = "Gareth Edwards", YearOfRelease = 2014, BoxOfficeRevenue = 529_000_000.00m }); context.SaveChanges(); }
When you insert the record, SQL Server will generate the value for you and EF Core will update the property with the auto-generated value.
Option 2 – Turn on IDENTITY_INSERT
In some cases, you may want to explicitly set the id instead of letting it get auto-generated for you. In this case, you would need to turn on IDENTITY_INSERT, like this:
Code language: C# (cs)
using (var context = new StreamingServiceContext(connectionString)) { using (var transaction = context.Database.BeginTransaction()) { context.Movies.Add(new Movie() { Id = 20, Name = "Godzilla", Description = "Nuclear lizard fights monsters", Director = "Gareth Edwards", YearOfRelease = 2014, BoxOfficeRevenue = 529_000_000.00m }); context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT dbo.Movies ON;"); context.SaveChanges(); context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT dbo.Movies OFF;"); transaction.Commit(); } }
Note: If you’re using EF Core, you have to execute the query within a transaction for this to work.
IDENTITY_INSERT can only be ON for one table at a time per session.
Let’s say you try to turn on IDENTITY_INSERT for two tables at once:
Code language: C# (cs)
context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT dbo.Movies ON;"); context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT dbo.Actors ON;");
You’ll get the following exception:
Microsoft.Data.SqlClient.SqlException (0x80131904): IDENTITY_INSERT is already ON for table ‘StreamingService.dbo.Movies’. Cannot perform SET operation for table ‘dbo.Actors’.
This restriction only applies per session. If some other session turns on IDENTITY_INSERT for the Actors table in their session, you can turn on IDENTITY_INSERT for Movies in a different session at the same time.
Option 3 – Remove the IDENTITY specification from the column
If you’re in a dev environment, and didn’t realize you had an identity column until you ran into this identity insert exception, then chances are you simply want to remove the IDENTITY specification from the column.
If you’re using EF Core to create your tables, use the DatabaseGenerated(DatabaseGeneratedOption.None)) attribute to specify that the column shouldn’t be an identity column.
using System.ComponentModel.DataAnnotations.Schema; public class Movie { [Key] [DatabaseGenerated(DatabaseGeneratedOption.None)] public int Id { get; set; } //rest of class }Code language: C# (cs)
EF Core doesn’t handle this schema change correctly. Instead of trying to do this as a schema change, redo the migration that created the table.
For example, let’s say you have two migrations – Database_v1_Init and Database_v2_CreateMoviesTable – and you want to change the Movies table so it doesn’t have the identity column. To redo the Database_v2_CreateMoviesTable migration, do the following steps:
- Migrate down to Database_v1_Init:
Code language: PowerShell (powershell)
dotnet ef database update Database_v1_Init
- Remove the last migration, which in this case is Database_v2_CreateMoviesTable:
Code language: PowerShell (powershell)
dotnet ef migrations remove
Note: Don’t just delete the migration file, since the Model snapshot file will get out of sync.
- Add the [DatabaseGenerated(DatabaseGeneratedOption.None)] attribute to the Movie.Id property.
Code language: C# (cs)
public class Movie { [Key] [DatabaseGenerated(DatabaseGeneratedOption.None)] public int Id { get; set; }
- Recreate the migration Database_v2_CreateMoviesTable:
Code language: PowerShell (powershell)
dotnet ef migrations add Database_v2_CreateMoviesTable
- Look at the generated migration source code in <timestamp>_Database_v2_CreateMoviesTable.cs. First, you can see that it’s not creating the column with an IDENTITY specification. Second, the only thing this migration should be doing is creating the Movies table. If it’s doing anything else, then it’s likely the Model snapshot file got into an invalid state (probably due to manually deleting the migration files).
Code language: C# (cs)
public partial class Database_v2_CreateMoviesTable : Migration { protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.CreateTable( name: "Movies", columns: table => new { Id = table.Column<int>(type: "int", nullable: false), Name = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: false), YearOfRelease = table.Column<int>(type: "int", nullable: false), Description = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: false), Director = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false), BoxOfficeRevenue = table.Column<decimal>(type: "decimal(18,2)", nullable: false) }, constraints: table => { table.PrimaryKey("PK_Movies", x => x.Id); }); //rest of class not shown }
- Apply the migration:
Code language: PowerShell (powershell)
dotnet ef database update Database_v2_CreateMoviesTable
Now that that id column no longer has the IDENTITY specification, you can insert records into the table while specifying a value for the id.
Disclaimer: This doesn’t apply to production environments. You’ll lose data if you drop and recreate the table. I would only recommend this approach if you’re in a dev environment and OK with losing data.
Option 4 – If doing an update, fetch the record first
To do an update instead of an insert, have you fetch the record first. Otherwise when you call SaveChanges(), EF Core will generate an insert statement. If you tried to specify the value for the identity column, then you’ll run into the identity insert exception.
Here’s how to update a record by fetching it first:
Code language: C# (cs)
using (var context = new StreamingServiceContext(connectionString)) { var movie = await context.Movies.FirstOrDefaultAsync(t => t.Id == 20); movie.Description = "Nuclear lizard fights monsters"; context.SaveChanges(); }
SQL Server 2019 on Windows SQL Server 2019 on Linux SQL Server 2016 Service Pack 2 SQL Server 2016 Developer SQL Server 2016 Enterprise SQL Server 2016 Enterprise Core SQL Server 2016 Standard SQL Server 2017 on Linux SQL Server 2017 on Windows More…Less
Symptoms
Assume that you use INSERT EXEC statement to insert a row that contains an explicit identity value into a table that has IDENTITY column and IDENTITY_INSERT is OFF by default in Microsoft SQL Server. You notice that the INSERT EXEC statement doesn’t work correctly. The expected behavior is that the statement fails and returns the following error message:
Cannot insert explicit value for identity column in table ‘<TableName>’ when IDENTITY_INSERT is set to OFF
Status
Microsoft has confirmed that this is a problem in the Microsoft products that are listed in the «Applies to» section.
Resolution
This issue is fixed in the following cumulative updates for SQL Server:
-
Cumulative Update 6 for SQL Server 2019
-
Cumulative Update 22 for SQL Server 2017
-
Cumulative Update 14 for SQL Server 2016 SP2
About cumulative updates for SQL Server:
Each new cumulative update for SQL Server contains all the hotfixes and all the security fixes that were included with the previous cumulative update. Check out the latest cumulative updates for SQL Server:
-
Latest cumulative update for SQL Server 2019
-
Latest cumulative update for SQL Server 2017
-
Latest cumulative update for SQL Server 2016
References
Learn about the terminology that Microsoft uses to describe software updates.
Need more help?
- Remove From My Forums
-
Question
-
I am writing a program to import data across from one database to another. I need to be able to make it use the current ID numbers or else the relations will be broken.
I keep getting:
Cannot insert explicit value for identity column in table ‘mytable’ when IDENTITY_INSERT is set to OFF.
I have opened up SQL Server Management Studio created a new query with:
SET IDENTITY_INSERT [BMSSUNRISE].[dbo].[SystemInventory] ON
GOthis results in success but the program still fails, I have tested the Insert SQL statement in the SQL Studio tool and included the above line in front of it and it works.
MY QUESTION, how do I get VB.NET2005 to set this option on?
I have tried to place that line above in the insert command of the table adapter but it comes up with an error saying that SET is not supported. There must be a way to be able to «enable» this using the dynamic classes that a generated.
Any help is muchly appreciated, thankyou.
Regards,
Michael Proctor
Answers
-
Have you tried using an SqlCommand object, and executing the statement as SQL?
There’s an example of how to do this in the following article:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnhcvs04/html/vs04i1.aspHere’s a code snippet from the article:
dap1 = New SqlClient.SqlDataAdapter _
("SELECT ShipperID, CompanyName, Phone " & _
"FROM Shippers", SqlConnection1)
dap1.InsertCommand = New SqlClient.SqlCommand _
("SET IDENTITY_INSERT Shippers ON ")
dap1.InsertCommand.CommandText &= _
"INSERT INTO Shippers " & _
"(ShipperID, CompanyName, Phone) " & _
"VALUES (@ShipperID, @CompanyName, @Phone)"
dap1.InsertCommand.Connection = SqlConnection1Dim prm1 As SqlClient.SqlParameter = _
dap1.InsertCommand.Parameters.Add _
("@ShipperID", SqlDbType.Int)
prm1.SourceColumn = "ShipperID"
prm1.SourceVersion = DataRowVersion.Current
Dim prm2 As SqlClient.SqlParameter = _
dap1.InsertCommand.Parameters.Add _
("@CompanyName", SqlDbType.NVarChar, 40)
prm2.SourceColumn = "CompanyName"
Dim prm3 As SqlClient.SqlParameter = _
dap1.InsertCommand.Parameters.Add _
("@Phone", SqlDbType.NVarChar, 24)
prm3.SourceColumn = "Phone" -
Thanks for your suggestions Christopher, I completed my project tonight YAY!
In the end the opening a connection and running my SQL statement then the Update method works 100% of the time even on tables with over 200,000+ records so it seems that the connection does stay pinned up during the update method 🙂
Funny you should say about the Upsizing Wizard, although I am sure it does a great job on some databases unfortunately it doesn’t do so well on ours. It had major issues with dates fields not being of SQL type and also problems with Queries as i have VBA functions in them.
In the end a custom program to transpose the data into SQL valid data seemed to be my only answer (however MSFT did suggest SSIS which I looked into and did trial, it would have worked also as you can customise it’s transfer of data, however I had already completed over 50% of my project so just kept going)
Pity Microsoft don’t have a property or method to allow this simply from the TableAdapter, however I had an idea (if I had to do this again) which is to overload the Update Method and have an additional parameter of IDENTITYINSERT as boolean and if so open the connection pass the SQL state then run the MS Update method and close it up. Then you would have to worry about coding each time you run the Update.
Anyways acheived what I needed and again thanks for your assistance.
Примечание: модератор удалил этот ответ как дубликат и оставил мой другой ответ на вопрос только с тегом sql-server (это был первый вопрос, на который я пришел из Google). Поскольку этот вопрос имеет тег фреймворка сущности, ответ снова публикуется здесь.
Это для EntityFramework Core 3.1.22. Использование неправильного свойства для указания внешнего ключа приводит к тому, что Entity Framework понижает первичный ключ до… чего-то другого. Затем Entity Framework всегда будет пытаться вставить явное значение, которое создает исключение базы данных, поскольку не может вставить значение, которое, как ему было сказано, является первичным ключом и не должно быть вставлено.
Microsoft.EntityFrameworkCore.DbUpdateException: 'An error occurred while updating the entries. See the inner exception for details.'
Inner Exception:
SqlException: Cannot insert explicit value for identity column in table 'FOO' when IDENTITY_INSERT is set to OFF.
Пример кода. У нас есть сопоставление классов 1-к-1:
public class Foo /* child */
{
public int FooPrimaryKey { get; set; }
public int BarPrimaryKey { get; set; }
public virtual Bar PropertyBar {get; set; }
}
public class Bar
{
public int BarPrimaryKey { get; set; }
public virtual Foo PropertyFoo {get; set; }
}
modelBuilder.Entity<Foo>(entity =>
{
entity.HasKey(e => e.FooPrimaryKey);
entity.ToTable("FOO", "dbo");
entity.HasOne(d => d.PropertyBar)
.WithOne(x => x.PropertyFoo)
// wrong, this throws the above exception
.HasForeignKey<Bar>(x => x.BarPrimaryKey);
});
Вместо этого внешний ключ должен быть (тот же ключ, другой тип):
.HasForeignKey<Foo>(x => x.BarPrimaryKey);