更新数据库returns 主键错误ASP.NET mvc 5
Updating database returns primary key error ASP.NET mvc 5
我正在按照 this 教程创建我自己的自定义 "blog" 功能,但它不是创建博客文章,而是创建 "projects" 带有标题、创建日期、简短说明、详细说明和团队负责人。
如果传入 url 的 int 与其主键匹配,则以下代码应该更改项目的信息,如果不匹配,则使用上述所有参数创建一个新项目。
但是,当它达到 model.SaveChanges(如下所示)时,它会抛出错误。
我知道我在 MVC 5 中工作,教程在 MVC 3 中,但到目前为止,一切都已经翻译得很好。
这是我的控制器:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SouthMeckNTHS.Models;
using SouthMeckNTHS.Extensions;
using System.Text;
namespace SouthMeckNTHS.Controllers
{
public class ProjectsController : Controller
{
private ProjectsModel model = new ProjectsModel();
// GET: Projects
public ActionResult Index()
{
return RedirectToAction("My");
}
[Authorize]
public ActionResult My()
{
return View();
}
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Update(int? id, string title, string shortDescription, string longDescription, DateTime dateTime, string technologies)
{
//REMEMBER TO ADD PROJECT LEADER FUNCTIONALITY!!
if (!User.IsInRole("ChapterAdvisor"))
{
RedirectToAction("Index");
}
Project project = GetProject(id);
project.Title = title;
project.ShortDescription = shortDescription;
project.LongDescription = longDescription;
project.TimeCreated = dateTime;
project.ProjectLeader = User.Identity.GetFirstName() + " " + User.Identity.GetLastName();
project.Technologies.Clear();
technologies = technologies ?? string.Empty;
string[] technologyNames = technologies.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
foreach (string technologyName in technologyNames)
{
project.Technologies.Add(GetTechnology(technologyName));
}
if (!id.HasValue)
{
model.Projects.Add(project);
}
try
{
model.SaveChanges();
}
catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
{
Exception raise = dbEx;
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
string message = string.Format("{0}:{1}",
validationErrors.Entry.Entity.ToString(),
validationError.ErrorMessage);
// raise a new exception nesting
// the current instance as InnerException
raise = new InvalidOperationException(message, raise);
}
}
throw raise;
}
return RedirectToAction("Details", new { id = project.Id });
}
[ValidateInput(false)]
public ActionResult Edit(int? id)
{
Project project = GetProject(id);
StringBuilder technologyList = new StringBuilder();
foreach (Technology technology in project.Technologies)
{
technologyList.AppendFormat("{0} ", technology.Name);
}
ViewBag.Technologies = technologyList.ToString();
return View(project);
}
private Technology GetTechnology(string technologyName)
{
return model.Technologies.Where(x => x.Name == technologyName).FirstOrDefault() ?? new Technology() { Name = technologyName };
}
private Project GetProject(int? id)
{
return id.HasValue ? model.Projects.Where(x => x.Id == id).First() : new Project() { Id = 0 };
}
[Authorize]
public ActionResult Join()
{
return View();
}
}
}
这是视图:
@model SouthMeckNTHS.Models.Project
@using SouthMeckNTHS.Extensions;
@{
ViewBag.Title = "Edit";
}
<br />
<br />
<br />
<br />
<br /><br />
<form action="@Href("~/Projects/Update")" method="post" id="postForm">
@Html.AntiForgeryToken()
@if (Model.Id != 0)
{
<input type="hidden" name="id" value="@Model.Id" />
}
@{ DateTime dateTime = Model.TimeCreated.Year > 2000 ? Model.TimeCreated : DateTime.Now; }
<input type="text" name="dateTime" value="@dateTime" /> Date<br />
<input type="text" name="title" value="@Model.Title" /> Project Name<br />
@Html.DropDownListFor(m => m.Technologies, new SelectList(new List<Object> { new { value = "Animation", text = "Animation" }, new { value = "Robotics", text = "Robotics" }, new { value = "Architecture", text = "Architecture" }, new { value = "CAD", text = "CAD" }, new { value = "Websites", text = "Websites" }, new { value = "Games", text = "Games" }, new { value = "Biotechnology", text = "Biotechnology" }, new { value = "Club", text = "Club" }, new { value = "Other", text = "Other" } }, "value", "text"), new { @style = "border: 1px solid #e8e8e8;padding: 0.5em 1.07em 0.5em;background: #f5f5f5;font-size: 0.875rem;border-radius: 5px;width: 100%;line-height: 1.43;min-height: 3.5em;" })
<textarea name="shortDescription" rows="5" cols="80">@Model.ShortDescription</textarea><br />
<textarea name="longDescription" rows="10" cols="80">@Model.LongDescription</textarea><br />
<input type="submit" name="submit" value="Save Changes" />
</form>
**这是我得到的错误:
Click Here to View the image
^上图是读错:
违反 PRIMARY KEY 约束 'PK__Projects__3214EC0766FE6300'。无法在 object 'dbo.Projects' 中插入重复键。重复键值为 (0)。
声明已终止。
以及后面的文字。
知道什么是 happening/how 来修复它以及为什么它对我不起作用吗?
我不明白为什么教程的示例在我的几乎相同时不会抛出关于 "duplicate keys" 的错误。
我认为 ef 正在尝试附加实体(添加它)而不是修改它,我猜这是因为您的上下文正在跟踪实体可能是因为您对 get 的调用,请尝试使用 find 而不是 first,因为 find
The Find method on DbSet uses the primary key value to attempt to find an entity tracked by the context. If the entity is not found in the context then a query will be sent to the database to find the entity there. Null is returned if the entity is not found in the context or in the database.
所以你在更新它时没有跟踪这个实体,因为你正在更新被跟踪的实体本身。
所以在你的 GetProject 中,替换这个
model.Projects.Where(x => x.Id == id).First()
有了这个
model.Projects.Find(id)
我正在按照 this 教程创建我自己的自定义 "blog" 功能,但它不是创建博客文章,而是创建 "projects" 带有标题、创建日期、简短说明、详细说明和团队负责人。
如果传入 url 的 int 与其主键匹配,则以下代码应该更改项目的信息,如果不匹配,则使用上述所有参数创建一个新项目。
但是,当它达到 model.SaveChanges(如下所示)时,它会抛出错误。 我知道我在 MVC 5 中工作,教程在 MVC 3 中,但到目前为止,一切都已经翻译得很好。
这是我的控制器:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SouthMeckNTHS.Models;
using SouthMeckNTHS.Extensions;
using System.Text;
namespace SouthMeckNTHS.Controllers
{
public class ProjectsController : Controller
{
private ProjectsModel model = new ProjectsModel();
// GET: Projects
public ActionResult Index()
{
return RedirectToAction("My");
}
[Authorize]
public ActionResult My()
{
return View();
}
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Update(int? id, string title, string shortDescription, string longDescription, DateTime dateTime, string technologies)
{
//REMEMBER TO ADD PROJECT LEADER FUNCTIONALITY!!
if (!User.IsInRole("ChapterAdvisor"))
{
RedirectToAction("Index");
}
Project project = GetProject(id);
project.Title = title;
project.ShortDescription = shortDescription;
project.LongDescription = longDescription;
project.TimeCreated = dateTime;
project.ProjectLeader = User.Identity.GetFirstName() + " " + User.Identity.GetLastName();
project.Technologies.Clear();
technologies = technologies ?? string.Empty;
string[] technologyNames = technologies.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
foreach (string technologyName in technologyNames)
{
project.Technologies.Add(GetTechnology(technologyName));
}
if (!id.HasValue)
{
model.Projects.Add(project);
}
try
{
model.SaveChanges();
}
catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
{
Exception raise = dbEx;
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
string message = string.Format("{0}:{1}",
validationErrors.Entry.Entity.ToString(),
validationError.ErrorMessage);
// raise a new exception nesting
// the current instance as InnerException
raise = new InvalidOperationException(message, raise);
}
}
throw raise;
}
return RedirectToAction("Details", new { id = project.Id });
}
[ValidateInput(false)]
public ActionResult Edit(int? id)
{
Project project = GetProject(id);
StringBuilder technologyList = new StringBuilder();
foreach (Technology technology in project.Technologies)
{
technologyList.AppendFormat("{0} ", technology.Name);
}
ViewBag.Technologies = technologyList.ToString();
return View(project);
}
private Technology GetTechnology(string technologyName)
{
return model.Technologies.Where(x => x.Name == technologyName).FirstOrDefault() ?? new Technology() { Name = technologyName };
}
private Project GetProject(int? id)
{
return id.HasValue ? model.Projects.Where(x => x.Id == id).First() : new Project() { Id = 0 };
}
[Authorize]
public ActionResult Join()
{
return View();
}
}
}
这是视图:
@model SouthMeckNTHS.Models.Project
@using SouthMeckNTHS.Extensions;
@{
ViewBag.Title = "Edit";
}
<br />
<br />
<br />
<br />
<br /><br />
<form action="@Href("~/Projects/Update")" method="post" id="postForm">
@Html.AntiForgeryToken()
@if (Model.Id != 0)
{
<input type="hidden" name="id" value="@Model.Id" />
}
@{ DateTime dateTime = Model.TimeCreated.Year > 2000 ? Model.TimeCreated : DateTime.Now; }
<input type="text" name="dateTime" value="@dateTime" /> Date<br />
<input type="text" name="title" value="@Model.Title" /> Project Name<br />
@Html.DropDownListFor(m => m.Technologies, new SelectList(new List<Object> { new { value = "Animation", text = "Animation" }, new { value = "Robotics", text = "Robotics" }, new { value = "Architecture", text = "Architecture" }, new { value = "CAD", text = "CAD" }, new { value = "Websites", text = "Websites" }, new { value = "Games", text = "Games" }, new { value = "Biotechnology", text = "Biotechnology" }, new { value = "Club", text = "Club" }, new { value = "Other", text = "Other" } }, "value", "text"), new { @style = "border: 1px solid #e8e8e8;padding: 0.5em 1.07em 0.5em;background: #f5f5f5;font-size: 0.875rem;border-radius: 5px;width: 100%;line-height: 1.43;min-height: 3.5em;" })
<textarea name="shortDescription" rows="5" cols="80">@Model.ShortDescription</textarea><br />
<textarea name="longDescription" rows="10" cols="80">@Model.LongDescription</textarea><br />
<input type="submit" name="submit" value="Save Changes" />
</form>
**这是我得到的错误: Click Here to View the image
^上图是读错:
违反 PRIMARY KEY 约束 'PK__Projects__3214EC0766FE6300'。无法在 object 'dbo.Projects' 中插入重复键。重复键值为 (0)。 声明已终止。
以及后面的文字。
知道什么是 happening/how 来修复它以及为什么它对我不起作用吗? 我不明白为什么教程的示例在我的几乎相同时不会抛出关于 "duplicate keys" 的错误。
我认为 ef 正在尝试附加实体(添加它)而不是修改它,我猜这是因为您的上下文正在跟踪实体可能是因为您对 get 的调用,请尝试使用 find 而不是 first,因为 find
The Find method on DbSet uses the primary key value to attempt to find an entity tracked by the context. If the entity is not found in the context then a query will be sent to the database to find the entity there. Null is returned if the entity is not found in the context or in the database.
所以你在更新它时没有跟踪这个实体,因为你正在更新被跟踪的实体本身。 所以在你的 GetProject 中,替换这个
model.Projects.Where(x => x.Id == id).First()
有了这个
model.Projects.Find(id)