IDENTITY_INSERT设置为OFF时,无法为表中的标识列插入显式值。”

时间:2018-10-05 09:43:27

标签: asp.net-core entity-framework-core

对于我的API,我正在使用Entity Framework Core进行代码优先迁移。我创建了一些工作正常的关系。现在,我添加了另一个关系(一对多),突然我被这个错误拍到耳边:

Cannot insert explicit value for identity column in table 'Companies' when IDENTITY_INSERT is set to OFF."

在场外,我肯定做错了什么,但我只是不知道什么。我遇到了更多类似这样的问题,答案是“将IDENTITY_INSERT设置为ON”,但这对我不起作用,因为EF正在处理一切。

可以属于某个组的“我的公司”类别:

public class Company
{

// Primary key
public int Id { get; set; }

// The optional Id of a Group
public int? GroupID { get; set; }

...

}

还有Group类:

public class Group
{

// Primary key
public int Id { get; set; }

// Name of the Group
public string Name { get; set; }

// List of Companies in this group
public IEnumerable<Company> Companies { get; set; }
}

用于处理POST的代码:

// POST api/groups
[HttpPost]
public async Task<IActionResult> Post([FromBody] Group group)
{
  try
  {
    if (ModelState.IsValid)
    {
      _context.Groups.Add(group);
      await _context.SaveChangesAsync();
      return CreatedAtRoute("GetGroup", new { id = group.Id }, group);
    }

    return BadRequest(ModelState);
  }
  catch (Exception e)
  {
    return BadRequest($"Unable to create: {e.Message}");
  }
}

在我的数据库中,所有列,索引和键均按预期方式创建,就像我在API中获得的其他一对多关系一样。但是这个特定的案例似乎最终陷入了痛苦之中……

我要添加到数据库中的类:

4 个答案:

答案 0 :(得分:1)

问题在于,EF没有任何提示,可以知道是否正在显式插入Company(在Group关系下),或者是否应该使用数据库中预先存在的那个。

由于实例实例已与DbContext断开连接,因此在EF尝试生成其SQL命令时,没有迹象表明它们在数据库中是否存在。

这里没有简单的方法,至少在我使用EF Core玩游戏时没有。

您应该:

  1. 将代码更改为仅使用ID而不是导航属性,以便尽可能避免使用此代码,或者;
  2. 在保存所需数据之前(例如:在保存Company之前,更改代码以获取相关数据(例如:获取Group并将其附加到Group)。

例如,

var companyDB = await context.Companies.SingleOrDefaultAsync(c => c.Id == group.Company.Id);
group.Company = companyDB;
context.Groups.Add(group);
await context.SaveChangesAsync();

是的,您要两次访问数据库。这就是为什么我建议使用第一种方法的原因,因此您可以避免这种提取,而只需将Group实体直接保存到DB中即可。

但是,这并不禁止您向视图发送Company导航实例。只需创建一些与数据库相关的与实体相关的类,以便您可以使用此实体类型加载/保存数据,并创建一个Dto对象,该对象将在需要时用作端点输入/输出。

可以使用AutoMapper,手动linq或其他方法将彼此绑定在一起。

答案 1 :(得分:0)

这是因为您要在设置为标识(自动递增)的列中传递一些值。

我认为您要插入的Group实体具有要尝试将其值插入到公司表中的ID的公司作为子记录。并引发错误。

答案 2 :(得分:0)

在尝试保存与现有实体(属性library(shiny) library(shinyjs) # The tab need to be closed programmatically; here is a quick solution # https://github.com/daattali/advanced-shiny/blob/master/close-window/app.R jscode <- "shinyjs.closeWindow = function() { window.close(); }" # App One appOne <- list( ui = fluidPage( useShinyjs(), extendShinyjs(text = jscode, functions = c("closeWindow")), fluidRow( column(3), mainPanel(h2("Welcome to the load page"), plotOutput("plot"), actionButton("quit", "QUIT", class = "btn-warning"))) ), server = function(input, output, session) { output$plot <- renderPlot({ with(cars, hist(dist, breaks = 10)) }) observeEvent(input$quit, { js$closeWindow(); stopApp("appRoute") }) } ) # App TWO appTwo <- list( ui = fluidPage( useShinyjs(), extendShinyjs(text = jscode, functions = c("closeWindow")), fluidRow( column(3), mainPanel(h2("Welcome to appTwo"), plotOutput("plot"), actionButton("quit", "QUIT", class = "btn-warning"))) ), server = function(input, output, session) { output$plot <- renderPlot({ plot(cars) }) observeEvent(input$quit, { js$closeWindow(); stopApp("appRoute") }) } ) # Router appRoute <- list( ui = fluidPage( useShinyjs(), extendShinyjs(text = jscode, functions = c("closeWindow")), fluidRow( column(3), mainPanel(h2("Welcome to Selector"), actionButton("appOne", "AppOne"), actionButton("appTwo", "AppTwo"), actionButton("appEnd", "END", class = "btn-danger") )) ), server = function(input, output, session) { observeEvent(input$appOne, { js$closeWindow(); stopApp("appOne") }) observeEvent(input$appTwo, { js$closeWindow(); stopApp("appTwo") }) observeEvent(input$appEnd, { js$closeWindow(); stopApp("appEnd") }) } ) # Main loop route <- "appRoute" while (TRUE) { app <- switch( route, appRoute = shinyApp(appRoute$ui, appRoute$server), appOne = shinyApp(appOne$ui, appOne$server), appTwo = shinyApp(appTwo$ui, appTwo$server), appEnd = "END" ) if (is.null(app)) { # not matched warning("Unknown route ", route) route <- "appRoute" next } else if (is.character(app)) { # final end message("Ending") break } # Execute a new app and retrieve return code route <- print(app) message("New route ", route) # browser() } 具有多对一关系并指向{{1}的实体(例如Cat)时,我遇到了类似的问题})。除了a)在保存实体(Owner)之前从数据库获取关系(Person),以及b)向实体(Person)添加另一个属性(Cat),我发现了我认为是最好的解决方案:c)仅坚持“导航”属性(不要创建额外的int PersonId属性),并且在需要引用时,使用Cat

答案 3 :(得分:0)

Entity Framework 由于某种原因丢失了跟踪,Entity Framework 需要为已经存在的实体重新建立跟踪。

您可以通过以下方式获取实体跟踪的状态:

var entityTrackingState = _context.Entry(entity).State;

您可以通过以下方式强制实体框架对现有实体进行跟踪:

_context.Entry(untrackedEntity).State = EntityState.Unchanged;

哪里

_context 

是一个实体框架 DbContext。

强制跟踪解决了我的问题,但确实应该在实体框架丢失跟踪的地方进行调试。

相关问题