尽管违反PRIMARY KEY约束已被回答了好几次,但是没有一个不能解决我的问题。考虑下面的模型。每个Course
对象可以拥有多个资源,每个CourseResource
可以属于多个课程。
public class Course
{
public int Id {get; set;}
// other properties
public IList<CourseResourse> CourseResources {get; set;}
}
public class CourseResouce
{
public int Id {get; set;}
// other properties
public IList<Course> Courses {get; set;}
}
Course
模型的编辑操作是:
public ActionResult Edit(int? id)
{
if (id == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
Course course = db.Courses
.Include(x => x.CourseResources)
.Where(x => x.Id == id)
.AsNoTracking()
.FirstOrDefault();
if (course == null)
return HttpNotFound();
db.Detach(course.CourseResources);
CourseVm courseVm = new CourseVm()
{
Course = course,
// other properties
};
return View(courseVm);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(CourseVm courseVm)
{
if (ModelState.IsValid)
{
IList<int> rsIds = courseVm.Course.CourseResources.Select(x => x.Id).ToList();
Course c = db.Courses.Find(courseVm.Course.Id);
if (c.IsNotNull())
{
db.Entry(c).State = EntityState.Modified;
db.SaveChanges();
foreach (var resourceId in rsIds)
{
var rs = db.CourseResources.SingleOrDefault(x => x.Id == resourceId);
if (rs.IsNotNull())
c.CourseResources.Add(rs);
}
db.Entry(c).State = EntityState.Modified;
db.SaveChanges(); // <- Error here
}
return RedirectToAction("Index");
}
说明:
我尝试从CourseResources
分离子对象(course
)
从收到的Course
(ViewModel)中清除资源
保存课程
然后向其中添加新的CourseResourse
当我尝试保存异常时会引发
违反PRIMARY KEY约束'PK_dbo.CourseTypeCourses'。无法在对象'dbo.CourseTypeCourses'中插入重复的密钥。
我在做什么错?预先感谢
答案 0 :(得分:1)
我必须假定“ dbo.CourseTypeCourses”是同时包含Cources和CourceResources键的中间表,并且您确实试图添加已经存在的记录。
请注意,您在GET方法中对CourceResources进行的分离操作不会传递该方法的结尾,因为您没有在db对象上保存任何更改(坦率地说,您不应在这种情况下使用所有)。因此,当您在POST方法中获取数据库对象时,就可以像开始时那样获取它们。
要进一步解释这一点,请注意Controller类实现IDisposable接口,在每个调用的末尾放置实例,并在每个调用的开始运行默认构造函数。因此,控制器属性(即db对象)的任何更改都不会通过调用的结尾。您的db对象以及控制器将在每次调用时进行初始化。
在我看来,进行您想做的事情的方法要简单得多:
因此,请尝试以下操作:
public ActionResult Edit(int? id)
{
if (id == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
Course course = db.Courses
.Include(x => x.CourseResources)
.Where(x => x.Id == id)
.AsNoTracking()
.FirstOrDefault();
if (course == null)
return HttpNotFound();
//db.Detach(course.CourseResources);
CourseVm courseVm = new CourseVm()
{
Course = course,
// other properties
};
return View(courseVm);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(CourseVm courseVm)
{
if (ModelState.IsValid)
{
IList<int> rsIds = courseVm.Course.CourseResources.Select(x => x.Id).ToList();
Course c = db.Courses
.Include(x => x.CourseResources)
.Where(x => x.Id == id)
.AsNoTracking()
.FirstOrDefault();
if (c.IsNotNull())
{
c.CourseResources.Clear();
foreach (var resourceId in rsIds)
{
var rs = db.CourseResources.SingleOrDefault(x => x.Id == resourceId);
if (rs.IsNotNull())
c.CourseResources.Add(rs);
}
db.Entry(c).State = EntityState.Modified;
db.SaveChanges();
}
return RedirectToAction("Index");
}
快乐的编码!