I've created a new ASP.NET Core 2.1 Web API. It uses EF Core, code first, to read and write to a SQL Server database. So I've used migrations to generate/scaffolding the database.
On the [HTTPPOST] action method in the controller, when it adds a new record to the DbContext and tries to save, I get the following error:
System.Data.SqlClient.SqlException (0x80131904): Cannot insert explicit value for identity column in table 'Readings' when IDENTITY_INSERT is set to OFF.
The database has only one table:
USE [eballcoz_mssql]
GO
/****** Object: Table [eballcoz_admin].[Readings] Script Date: 2018/11/08 21:13:34 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [eballcoz_admin].[Readings](
[Id] [int] IDENTITY(1,1) NOT NULL,
[BaseId] [int] NULL,
[Frequency] [int] NULL,
[Modulation] [int] NULL,
[Agc1] [int] NULL,
[Agc2] [int] NULL,
[TimeStamp] [datetime2](7) NULL,
CONSTRAINT [PK_Readings] 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]
GO
My model looks like this:
public class Reading
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public int? BaseId { get; set; }
public int? Frequency { get; set; }
public int? Modulation { get; set; }
public int? Agc1 { get; set; }
public int? Agc2 { get; set; }
public DateTime? TimeStamp { get; set; }
}
And my action method like this:
// POST: api/Readings/one
[HttpPost]
public async Task<IActionResult> PostReading([FromBody] Reading reading)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
_context.Readings.Add(reading);
await _context.SaveChangesAsync();
return CreatedAtAction("GetReading", new { id = reading.Id }, reading);
}
I understand what the problem is - my model inclues the "Id" primary key field, and so it's trying to write that to the database table, which SQL Server doesn't like. The problem is that I need the "Id" field in the model for when I read from the database. I would have thought that the [DatabaseGenerated(DatabaseGeneratedOption.Identity)] decorator in the model would tell EF that it should not try to insert the Id column, but it doesn't seem to be working. I've also tried to do this in FLUENT:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Reading>()
.HasKey(r => r.Id);
modelBuilder.Entity<Reading>()
.Property(r => r.Id)
.UseSqlServerIdentityColumn()
.ValueGeneratedOnAdd();
}
to no avail. How can I keep the Id column as part of my model, but tell EF not to include it in the INSERT query? I have read this:
There are basically 2 different ways to INSERT records without having an error:
- When the IDENTITY_INSERT is set OFF. The PRIMARY KEY "ID" MUST NOT BE PRESENT
- When the IDENTITY_INSERT is set ON. The PRIMARY KEY "ID" MUST BE PRESENT
So I'm basically trying to go for solution #1 - I don't want to supply a primary key value. I want SQL Server to automatically generate it for me. But my model does indeed include the Id column, because I need it when reading from the database... Any ideas?