【问题标题】:MVC - Cannot insert explicit value for identity column in table when IDENTITY_INSERT is set to OFFMVC - 当 IDENTITY_INSERT 设置为 OFF 时,无法在表中插入标识列的显式值
【发布时间】:2017-12-17 04:32:42
【问题描述】:

为我的模型提交创建表单时,我收到错误:

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

我可以看到这个问题被问了很多,但我对我的代码做了很多更改,但一点运气都没有。很抱歉,代码太多了,我通常会让人们在 cmets 中抱怨我没有发布足够的代码,所以我试图包括这次可能相关的所有内容。

我的控制器中抛出此错误的方法是:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult MaintenanceForm([Bind(Exclude = "project_clearance_id")]t_bcim_project_clearance project)
{
    if (ModelState.IsValid)
    {
        if (entities.t_bcim_project_clearance.Any(x => x.project_clearance_id == project.project_clearance_id))
        {
            entities.Entry(project).State = EntityState.Modified;
        }
        else
        {
            entities.t_bcim_project_clearance.Add(project);
        }
        entities.SaveChanges();
        return RedirectToAction("Maintenance", new { SubmissionNumber = project.Submission_Number, Mode = "Edit" });
    }
    var model = new ProjectViewModel()
    {
        Project = entities.t_bcim_project_clearance.Find(project.project_clearance_id),
        States = states,
        Branches = branches,
        Divisions = divisions,
        ProjectTypes = project_types,
        Statuses = statuses,
        ReadOnly = false,
        Mode = "Edit",
        Cleared = false
    };

    return RedirectToAction("Maintenance", new { SubmissionNumber = project.Submission_Number, Mode = "Edit" });
}

entities.SaveChanges(); 线上。 entities 是我连接 SQL 数据库的 Context 类。

下面是对应的GET方法:

[HttpGet]
public ActionResult MaintenanceForm(string SubmissionNumber, string Mode, int? id)
{
    if (!Mode.Equals("Edit", StringComparison.InvariantCultureIgnoreCase) && !Mode.Equals("View", StringComparison.InvariantCultureIgnoreCase))
    {
        throw new HttpException(400, "Mode must be either \"Edit\" or \"View\"");
    }

    var model = new ProjectViewModel()
    {
        Project = id.HasValue ? entities.t_bcim_project_clearance.Find(id) : (String.IsNullOrEmpty(SubmissionNumber) ? null : new t_bcim_project_clearance() { Submission_Number = Convert.ToDouble(SubmissionNumber) }),
        Statuses = statuses,
        Divisions = divisions,
        Branches = branches,
        ProjectTypes = project_types,
        States = states,
        Projects = entities.t_bcim_project_clearance.Where(s => s.Submission_Number.ToString().Equals(SubmissionNumber)),
        SubmissionNumber = SubmissionNumber,
        ReadOnly = (Mode == "View"),
        Mode = Mode,
        Cleared = false
    };

    return PartialView("_MaintenanceForm", model);
}

我的模型是一个 DBmodel。这是该模型中的违规属性:

namespace ProjectClearanceApp.Models
{
    using System;
    using System.Collections.Generic;

    public partial class t_bcim_project_clearance
    {
        // A lot of other properties
        public int project_clearance_id { get; set; }
    }
}

我创建了一个局部类来添加DataAnnotations,这里是:

namespace ProjectClearanceApp.Models
{
    [MetadataType(typeof(t_bcim_project_clearanceMetaData))]
    public partial class t_bcim_project_clearance
    {
    }

    public class t_bcim_project_clearanceMetaData
    {
        // a lot of other properties

        [Key]
        [Required]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int project_clearance_id { get; set; }
    }
}

我的project_clearance_id 被设置为我的表的主键,标识增量 = 1。

到目前为止我所做的尝试

  • 最初我的控制器正在生成具有预先计算的 ID 的新项目,所以显然我删除了它
  • 我将所有 DataAnnotations 添加到该部分类的 ID 属性中
  • 我以前在表单顶部有 Html.HiddenFor(model => model.project_clearance_id),但我删除了它
  • 我将[Bind(Exclude = "project_clearance_id")] 添加到 POST 方法的参数中

似乎没有任何效果。如果有人看到任何我可以更改的内容,将不胜感激。

编辑:我进入模型的 .edmx 图表,右键单击 project_clearance_id,打开属性,并将 StoreGeneratedPattern 更改为 Identity。现在,当我尝试创建新条目时代码可以正常工作,但是当我尝试编辑现有条目时,它会创建一个包含修改后字段的新条目,并且原始条目仍然像以前一样存在。

【问题讨论】:

  • 这是实体框架问题,不是 MVC 问题。
  • 好的,我的帖子中还有什么需要补充的吗?这并不能真正回答我的问题。
  • 我正在给你写一个答案,cmets 通常只是为了建议/询问更多信息/等等。我知道它没有回答你的问题
  • 所以我再说一遍,我的帖子中还应该包含其他内容吗?
  • 去掉视图代码,去掉asp.net、mvc、razor标签,添加实体框架标签。

标签: c# sql-server entity-framework


【解决方案1】:

您的问题是您正在尝试插入/更新数据库记录,并且在生成的 SQL 中,您将映射到 t_bcim_project_clearance 列的字段设置为特定值,但是由于您将此设置为不允许您这样做,因为它的值是自动设置的。

您需要确保映射到此列的对象中的值未修改或标记为已修改。

而不是使用entities.Entry(project).State = EntityState.Modified,设置每个属性实际上处于修改状态,以修改而不是对象本身。要将属性设置为已修改,您可以执行以下操作:

db.Entry(project).Property(x => x.PropertyName).IsModified = true;

当您执行.Add() 时,请确保属性project_clearance_id 的值设置为0。

编辑每个 cmets 的附加信息:

  • 如果您删除了Html.HiddenFor(model => model.project_clearance_id),请确保将其包含在您的视图中。如果您正在执行更新,则需要这样做。
  • 从您的参数中删除 [Bind(Exclude = "project_clearance_id")] 属性,因为您在执行更新时需要此值。

【讨论】:

  • t_bcim_project_clearance 不是列,它是我的模型所围绕的表的名称
  • 此外,当在新项目上引发此错误时,project_clearance_id.Add() 处设置的断点处设置为 0。我还将修改后的状态行更改为您对每个属性的建议(首先我尝试在此列表中包含project_clearance_id,然后我尝试不使用它),它仍然无法更新表中的项目。
  • 查看我的编辑。我用你建议的.IsModified 更改和我之前的代码一样尝试了这个 - 当我尝试编辑现有项目时,两者都会导致一个新项目。
  • 这种情况总会发生,因为你有[Bind(Exclude = "project_clearance_id")]。如果您正在执行更新,则需要该值。我的建议是将您的 API 分解为两个单独的端点。一种用于创建新的,一种用于更新。
  • 哇,谢谢!我删除了排除项并将Html.HiddenFor(model => model.Project.project_clearance_id) 重新添加到我的表单中,现在它可以正常用于创建和编辑。
猜你喜欢
  • 2016-05-13
  • 2016-08-18
  • 2019-03-10
  • 2010-11-22
  • 2011-08-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多