Sql server 使用EF Core 2.1从ASP.Net Core 2.1 Web API向SQL Server数据库插入记录时出错
我创建了一个新的ASP.NETCore2.1WebAPI。它使用EF核心(代码优先)读取和写入SQL Server数据库。因此,我使用迁移来生成/搭建数据库 在控制器中的[HTTPPOST]操作方法上,当它向DbContext添加新记录并尝试保存时,我得到以下错误: System.Data.SqlClient.SqlException(0x80131904):无法插入 表“读数”中标识列的显式值 标识\u插入被设置为关闭 数据库只有一个表:Sql server 使用EF Core 2.1从ASP.Net Core 2.1 Web API向SQL Server数据库插入记录时出错,sql-server,asp.net-core-2.1,ef-core-2.1,asp.net-core-webapi-2.1,Sql Server,Asp.net Core 2.1,Ef Core 2.1,Asp.net Core Webapi 2.1,我创建了一个新的ASP.NETCore2.1WebAPI。它使用EF核心(代码优先)读取和写入SQL Server数据库。因此,我使用迁移来生成/搭建数据库 在控制器中的[HTTPPOST]操作方法上,当它向DbContext添加新记录并尝试保存时,我得到以下错误: System.Data.SqlClient.SqlException(0x80131904):无法插入 表“读数”中标识列的显式值 标识\u插入被设置为关闭 数据库只有一个表: USE [eballcoz_mssql] GO /*
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
我的模型如下所示:
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; }
}
// 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);
}
我的行动方法是这样的:
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; }
}
// 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);
}
无济于事。如何将Id列作为模型的一部分,但告诉EF不要将其包含在INSERT查询中?我读过:
基本上有两种不同的方法可以插入记录而不会出错:
1) 当标识_INSERT被设置为OFF时。主键“ID”不能存在
2) 当IDENTITY_INSERT设置为ON时。主键“ID”必须存在
所以我基本上是在尝试解决方案#1-我不想提供主键值。我希望SQL Server自动为我生成它。但我的模型确实包含Id列,因为我在从数据库读取数据时需要它。。。有什么想法吗?实体框架已经解决了您所面临的问题。我相信你的问题在别处 EF的缺省行为 新建属性为
int
的对象时,其默认值为0。它不是可为null的类型,因此不能为null
。
当该属性(本例中的Id
被标记为自动递增主键时,EF Core在DbContext
中将其保留为0,直到调用SaveChanges()
,然后EF Core使用SQL Server为其生成的任何值填充Id
属性
var reading = new Reading(); //Id = 0
_context.Add(reading); //Id still 0
_context.SaveChanges(); //Id = 5 (or whatever Id from SQL
System.Console.Writeline($"Id: {reading.Id}" //output -> Id: 5
真正的问题是什么?
当您从客户端接收到Reading
对象(无论是发布到postdreading
操作)时,我猜测Id
字段此时已填充,导致您的错误
[HttpPost]
public async Task<IActionResult> PostReading([FromBody] Reading reading)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
//quick debug test
if (reading.Id > 0)
{
throw new ArgumentException("Something erroneously filled out the Id.");
}
_context.Readings.Add(reading);
await _context.SaveChangesAsync();
return CreatedAtAction("GetReading", new { id = reading.Id }, reading);
}
[HttpPost]
公共异步任务后期读取([FromBody]读取)
{
如果(!ModelState.IsValid)
{
返回请求(ModelState);
}
//快速调试测试
如果(reading.Id>0)
{
抛出新的ArgumentException(“Id填写错误的内容”);
}
_上下文。阅读。添加(阅读);
wait_context.SaveChangesAsync();
返回CreateDataAction(“GetReading”,new{id=reading.id},reading);
}
实体框架已经处理了您所看到的问题。我相信你的问题在别处
EF的缺省行为
新建属性为int
的对象时,其默认值为0。它不是可为null的类型,因此不能为null
。
当该属性(本例中的Id
被标记为自动递增主键时,EF Core在DbContext
中将其保留为0,直到调用SaveChanges()
,然后EF Core使用SQL Server为其生成的任何值填充Id
属性
var reading = new Reading(); //Id = 0
_context.Add(reading); //Id still 0
_context.SaveChanges(); //Id = 5 (or whatever Id from SQL
System.Console.Writeline($"Id: {reading.Id}" //output -> Id: 5
真正的问题是什么?
当您从客户端接收到Reading
对象(无论是发布到postdreading
操作)时,我猜测Id
字段此时已填充,导致您的错误
[HttpPost]
public async Task<IActionResult> PostReading([FromBody] Reading reading)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
//quick debug test
if (reading.Id > 0)
{
throw new ArgumentException("Something erroneously filled out the Id.");
}
_context.Readings.Add(reading);
await _context.SaveChangesAsync();
return CreatedAtAction("GetReading", new { id = reading.Id }, reading);
}
[HttpPost]
公共异步任务后期读取([FromBody]读取)
{
如果(!ModelState.IsValid)
{
返回请求(ModelState);
}
//快速调试测试
如果(reading.Id>0)
{
抛出新的ArgumentException(“Id填写错误的内容”);
}
_上下文。阅读。添加(阅读);
wait_context.SaveChangesAsync();
返回CreateDataAction(“GetReading”,new{id=reading.id},reading);
}
您应该在reading.Id检查。将对象添加到dbcontext时,它必须为0。您可以编辑它以强制:reading.Id=0代码>您应该在reading.Id检查。将对象添加到dbcontext时,它必须为0。您可以编辑它以强制:reading.Id=0代码>这个表面上的答案并不能解决根本问题,它只是掩盖了问题。我强烈建议不要这样做。这是一个潜在的问题,默认情况下Id应该是0,因此有另一个输入(或其他内容)发送其他内容的Id,模型绑定器在调用PostReading时获取该Id并将其放入reading对象中。因此OP应该确保表单中没有name=“id”的输入,因为他正在尝试添加新对象。但问题主要是关于EF方面的问题,我当时正在回答这个问题。这个表面上的答案并不能解决一个潜在的问题,它只是把问题掩盖起来。我强烈建议不要这样做。这是一个潜在的问题,默认情况下Id应该是0,因此有另一个输入(或其他内容)发送其他内容的Id,模型绑定器在调用PostReading时获取该Id并将其放入reading对象中。因此OP应该确保表单中没有name=“id”的输入,因为他正在尝试添加新对象。但问题主要是关于EF方面的事情,我正在回答这个问题。