如何使用实体框架代码执行CRUD? [英] How to perform CRUD with Entity Framework Code-First?

查看:95
本文介绍了如何使用实体框架代码执行CRUD?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我有一个非常简单的模型:

  public class Issue 
{
[Key]
public int IssueId {get;组; }
public int Number {get;组; }
public string标题{get;组; }
public DateTime Date {get;组; }

public virtual ICollection< Creator>创作者{get;组;
}

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

public virtual ICollection< Issue>问题{get;组; }
}

public class Icbd:DbContext
{
public DbSet< Issue>问题{get;组; }
public DbSet< Creator>创作者{get;组; }
}

我一直无法弄清楚如何更新多对多许多使用EF上下文的定位。在我的isnert /更新操作中,我有这个代码:

  [HttpPost] 
public ActionResult EditIssue(问题, int [] CreatorIds)
{
if(CreatorIds == null)
ModelState.AddModelError(CreatorIds,请至少指定一个创建者);

if(ModelState.IsValid)
{
//插入或更新问题记录(无关系)
if(issue.IssueId == 0)
db.Issues.Add(issue);
else
db.Entry(issue).State = System.Data.EntityState.Modified;
db.SaveChanges();

//删除 - 删除当前关系
如果(issue.Creators!= null)
{
issue.Creators = new List< Creator>();
db.Entry(issue).State = System.Data.EntityState.Modified;
db.SaveChanges();
}

//插入 - 获取多对多实例的创建者
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);
}

我可以插入问题我可以插入新的 issue.Creators 没有问题。但是,当我尝试删除当前的 issue.Creators ,所以我可以插入新的, issue.Creators 永远是空,所以它永远不会更新到一个空列表。我不明白这个 issue.Creators 中有记录,因为当代码继续插入新的创建者时,我会收到如下错误:

 违反PRIMARY KEY约束'PK__CreatorI__13D353AB03317E3D'。无法在对象'dbo.CreatorIssues'中插入重复键。 
该语句已被终止。

说明:在执行当前Web请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误的更多信息及其在代码中的起始位置。

异常详细信息:System.Data.SqlClient.SqlException:违反PRIMARY KEY约束PK__CreatorI__13D353AB03317E3D。无法在对象'dbo.CreatorIssues'中插入重复键。
该语句已被终止。

源错误:


第59行:issue.Creators = db.Creators.Where(x => CreatorIds.Contains(x.CreatorId))。 ToList();
第60行:db.Entry(issue).State = System.Data.EntityState.Modified;
第61行:db.SaveChanges();
第62行:
第63行:返回RedirectToAction(Index);

如何获取 issue.Creators 准确显示当前的关系,以便我可以删除它们。



更新:工作控制器



  [HttpPost] 
public ActionResult EditIssue(发行问题,int [] CreatorIds)
{
if(CreatorIds == null)
ModelState.AddModelError(CreatorIds ,请至少指定一位创作者);

if(ModelState.IsValid)
{
//插入或更新问题记录(无关系)
if(issue.IssueId == 0)
db.Issues.Add(issue);
else
db.Entry(issue).State = System.Data.EntityState.Modified;
db.SaveChanges();

//插入和更新许多关系
issue = db.Issues.Include(Creators)。其中(x => x.IssueId == issue.IssueId)。单();
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);
}


解决方案

加载它们为您 - 您的问题对象来自视图不会神奇地包含它们,除非您正确设置所有的绑定。



没有看到你的观点,可以'说出为什么,但足以说你必须加载它们,然后删除它们。您可以加载新的问题对象,然后尝试使用TryUpdateModel(问题)来更新该模型中的表单值。然后删除每个问题。创建者(如果这是预期的操作)

 

if(ModelState.IsValid )
{

var issueFromDb = db.Issues.Where(x => criteria here);
bool updateSuccessful = TryUpdateModel(issueFromDb);
foreach(var Creator in issueFromDb.Creators)
{
//删除创建者,如果你想要的
}




但是,如果您只想让所有创作者从页面返回而不加载,请检查绑定到可枚举。这里有很多帖子,还有一个: ASP.NET MVC3使用IEnumerable的模型绑定(不能推断类型)



如果关系存在,创建者应该通过加载问题。您不需要仅加载创建者。加载你的完整的模型,以确保它的工作,就像我在上面的编辑。你的代码应该可以正常工作,但可能需要.Include(Creators)尝试这样:

 
var testIssue = from o在db.Issues.Include(Creators)
其中o.IssueId == issue.IssueId
select o;
foreach(var creator in testIssue.Creators)
{
// check creator
}

这将让您知道创作者是否正确加载。


I am having a really hard time updating and deleting many to many relationships with EF Code-first.

I have a fairly simple Model:

    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; }
    }

I have been unable to figure out how to update the many-to-many realtionship using the EF context. In my isnert/update action, I have this code:

    [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);
    }

I can insert Issues and I can insert new issue.Creators without a problem. But, when I am trying to delete the current issue.Creators so I can then insert the new ones, issue.Creators is ALWAYS null so it will never update to an empty list. I don't understand this. issue.Creators has records in it because when the code proceeds to insert the new creators, I get an error like this:

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");

How do I get issue.Creators to accurately show the current relationships so I can delete them?

Update: Working 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);
    }

解决方案

The model binder isn't loading them up for you - your issues object coming from the view won't magically contain them unless you setup everything up properly for binding.

Without seeing your view one can't say why, but suffice to say you'll have to load them up, then delete them. You can load a new issues object and then do TryUpdateModel(issues) to get the form values updated into that model. Then delete each issues.Creators (if thats the intended action)


 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
   }




However if you just want all of your creators to come back from the page without loading, check out binding to an enumerable. there are many posts out there on this, heres one: ASP.NET MVC3 Model Binding using IEnumerable (Cannot infer type from)

If the relationship is there, the Creators should automatically load just by loading the Issue. You don't need to load only the creators. Load your full model to be sure its working as I did in the edit above. Your code 'should' work ok but its possible you need to .Include("Creators") try this:

var testIssue = from o in db.Issues.Include("Creators") 
where o.IssueId == issue.IssueId 
select o;
foreach(var creator in testIssue.Creators)
{
//check creator
}

this will let you know if "Creators" is loading properly.

这篇关于如何使用实体框架代码执行CRUD?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆