Como executar CRUD com o Entity Framework Code-First?
Estou com muita dificuldade em atualizar e excluir muitos e muitos relacionamentos com o EF Code-first.
Tenho um modelo bastante simples:
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; }
}
Não consegui descobrir como atualizar o realtion muitos-para-muitos usando o contexto EF. Na minha ação isnert / update, tenho este código:
[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);
}
Eu posso inserirIssues
e posso inserir novosissue.Creators
sem problemas. Mas, quando estou tentando excluir oissue.Creators
para que eu possa inserir os novos,issue.Creators
SEMPRE nulo para que nunca seja atualizado para uma lista vazia. Eu não entendo isso.issue.Creators
possui registros porque, quando o código continua a inserir os novos criadores, recebo um erro como este:
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");
Como eu consigoissue.Creators
para mostrar com precisão os relacionamentos atuais para que eu possa excluí-los?
[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);
}