我很难用EF Code-first更新和删除多对多关系。

我有一个相当简单的模型:

    public class Issue
    {
        [Key]
        public int      IssueId     { get; set; }
        public int      Number      { get; set; }
        public string   Title       { get; set; }
        public DateTime Date        { get; set; }

        public virtual ICollection<Creator> Creators { get; set; }
    }

    public class Creator
    {
        [Key]
        public int      CreatorId   { get; set; }
        public string   FirstName   { get; set; }
        public string   MiddleName  { get; set; }
        public string   LastName    { get; set; }

        public virtual ICollection<Issue> Issues { get; set; }
    }

    public class Icbd : DbContext
    {
        public DbSet<Issue> Issues { get; set; }
        public DbSet<Creator> Creators { get; set; }
    }

我一直无法弄清楚如何使用EF上下文更新多对多房地产。在我的通知/更新操作中,我有以下代码:
    [HttpPost]
    public ActionResult EditIssue ( Issue issue, int[] CreatorIds )
    {
        if(CreatorIds == null)
            ModelState.AddModelError("CreatorIds", "Please specify at least one creator");

        if(ModelState.IsValid)
        {
            // insert or update the issue record (no relationship)
            if (issue.IssueId == 0)
                db.Issues.Add(issue);
            else
                db.Entry(issue).State = System.Data.EntityState.Modified;
            db.SaveChanges();

            // delete - delete current relationships
            if (issue.Creators != null)
            {
                issue.Creators = new List<Creator>();
                db.Entry(issue).State = System.Data.EntityState.Modified;
                db.SaveChanges();
            }

            // insert - get creators for many-to-many realtionship
            issue.Creators = db.Creators.Where(x => CreatorIds.Contains(x.CreatorId)).ToList();
            db.Entry(issue).State = System.Data.EntityState.Modified;
            db.SaveChanges();

            return RedirectToAction("Index");
        }

        IssueEditModel issueEdit = new IssueEditModel{
            Creators = db.Creators.ToList(),
            Issue = issue,
        };
        return View(issueEdit);
    }

我可以插入Issues,也可以没有问题地插入新的issue.Creators。但是,当我尝试删除当前的issue.Creators以便可以插入新的issue.Creators时,issue.Creators始终为null,因此它将永远不会更新为空列表。我不明白issue.Creators中有记录,因为当代码继续插入新的创建者时,出现如下错误:
Violation of PRIMARY KEY constraint 'PK__CreatorI__13D353AB03317E3D'. Cannot insert duplicate key in object 'dbo.CreatorIssues'.
The statement has been terminated.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Data.SqlClient.SqlException: Violation of PRIMARY KEY constraint 'PK__CreatorI__13D353AB03317E3D'. Cannot insert duplicate key in object 'dbo.CreatorIssues'.
The statement has been terminated.

Source Error:


Line 59:    issue.Creators = db.Creators.Where(x => CreatorIds.Contains(x.CreatorId)).ToList();
Line 60:    db.Entry(issue).State = System.Data.EntityState.Modified;
Line 61:    db.SaveChanges();
Line 62:
Line 63:    return RedirectToAction("Index");

如何获得ojit_code来准确显示当前关系,以便删除它们?

更新:工作 Controller
    [HttpPost]
    public ActionResult EditIssue ( Issue issue, int[] CreatorIds )
    {
        if(CreatorIds == null)
            ModelState.AddModelError("CreatorIds", "Please specify at least one creator");

        if(ModelState.IsValid)
        {
            // insert or update the issue record (no relationship)
            if (issue.IssueId == 0)
                db.Issues.Add(issue);
            else
                db.Entry(issue).State = System.Data.EntityState.Modified;
            db.SaveChanges();

            // insert and update many to many relationship
            issue = db.Issues.Include("Creators").Where(x => x.IssueId == issue.IssueId).Single();
            issue.Creators = db.Creators.Where(x => CreatorIds.Contains(x.CreatorId)).ToList();
            db.Entry(issue).State = System.Data.EntityState.Modified;
            db.SaveChanges();

            return RedirectToAction("Index");
        }

        IssueEditModel issueEdit = new IssueEditModel{
            Creators = db.Creators.ToList(),
            Issue = issue,
        };
        return View(issueEdit);
    }

最佳答案

模型绑定(bind)器不会为您加载它们-来自 View 的问题对象不会神奇地包含它们,除非您正确地设置了所有内容以进行绑定(bind)。

没有看到您的观点,您不能说出原因,但足以说您必须先加载它们,然后将其删除。您可以加载一个新的issue对象,然后执行TryUpdateModel(issues)以将表单值更新到该模型中。然后删除每个问题。创建者(如果这是预期的操作)
if(ModelState.IsValid) { var issueFromDb = db.Issues.Where(x => criteria here); bool updateSuccessful = TryUpdateModel(issueFromDb); foreach(var creator in issueFromDb.Creators) { //delete creator if thats what you want }
但是,如果您只是想让所有创建者都从页面返回而无需加载,请 checkout 绑定(bind)到可枚举的对象。关于这一点,这里有很多帖子,这里是一个:ASP.NET MVC3 Model Binding using IEnumerable (Cannot infer type from)

如果存在关系,则创建者应仅通过加载问题来自动加载。您不需要仅加载创建者。加载完整的模型,以确保其能像我在上面的编辑中那样工作。您的代码“应该”可以正常工作,但可能需要.include(“Creators”)尝试以下操作:

var testIssue =来自db.Issues.Include(“Creators”)中的o
其中o.IssueId == issue.IssueId
选择o;
foreach(testIssue.Creators中的var创建者)
{
//检查创建者
}

这会让您知道“创建者”是否正确加载。

10-06 08:07