完整的插入/更新/删除实体框架儿童实体 [英] Complete Insert/Update/Delete of Child Entities in Entity Framework

查看:112
本文介绍了完整的插入/更新/删除实体框架儿童实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道它已经被问过,但长时间的搜索和编码我不能去工作和清洁方法之后。以下是我有:

I know it has been asked before, but after long hours of searching and coding I can't get to a working and clean approach. Here is what I have:

public class QuestionModel
{
    public int QuestionID { get; set; }
    public string QuestionText { get; set; }

    public IList<QuestionChoiceModel> Choices { get; set; }
}

public class QuestionChoiceModel
{
    public int ChoiceID { get; set; }
    public string ChoiceText { get; set; }
}

我使用EF 5为此ASP.Net MVC应用程序。通用Repository模式和依赖注入使用Ninject InRequestScope()到位和顺利开展。这些模型是从实体映射到/没有问题。

I'm using EF 5 for this ASP.Net MVC application. Generic Repository Pattern and Dependency Injection with Ninject using InRequestScope() are in place and work smoothly. These models are mapped to/from entities without a problem.

添加了新问题的数据库是直线前进。我设置一些QuestionChoice实例的问题属性,EF处理剩下的。

Adding new Questions to database is straight forward. I set Question property of some QuestionChoice instances, and EF handles the rest.

问题是更新的方式。假设我们在数据库中的问题与3 QuestionChoices:

The problem is about updates. Assume we have a Question in database with 3 QuestionChoices:

ChoiceID    QuestionID    ChoiceText
--------    ----------    ----------
1           1             blah blah
2           1             blah blah
3           1             blah blah

在打开一个问题的编辑页面(GET:/问题/编辑/ 1),我显示剃刀使用的foreach 这3个选择。我已经写了一些jQuery code,增加或删除输入元素,如果用户想所需的标记。因此,具有ID = 1的QuestionChoice可能在客户端进行编辑,ID = 2可能会被删除,并且新的ID = 4可能会增加。完美在用户presses保存按钮的表单数据绑定回QuestionModel(POST:/问题/编辑/ 1)。该模型是正确映射到一个问题的实体。这是故事开始的地方!

When edit page of a Question opens (GET: /Questions/Edit/1), I show these 3 choices using a foreach in Razor. I've written some JQuery code that adds or deletes required markup for input elements if user wants to. So, the QuestionChoice with ID=1 might be edited on client, ID=2 might be deleted, and a new ID=4 might be added. The form data is bound back to a QuestionModel perfectly when user presses the Save button (POST: /Questions/Edit/1). The model is mapped to a Question entity correctly. That is where the story begins!

现在的问题实体具有QuestionChoices其中一些已经在数据库的集合,一些应加入数据库,以及一些应从数据库中删除。

Now the Question entity has a collection of QuestionChoices some of which are already in database, some should be added to database, and some should be deleted from database.

我已经看了很多帖子,如:
<一href=\"http://stackoverflow.com/questions/18054798/entity-framework-not-saving-modified-children\">Entity框架不保存修改的子

I've read many posts like: Entity Framework not saving modified children

我可以处理在肮脏的方式编辑。并也有新的记录:

I can handle edits in that dirty way. And also new records by:

this._context.Entry(choice).State = EntityState.Added;

但我在寻找一个更优雅的方式。并且还处理应删除的记录。是否有完整的处理插入/更新/ EF使用在这种情况下子实体中删除一个好方法?说实话,我更期望从EF

But I'm looking for a more elegant way. And also handle records that should be deleted. Is there a good approach to handle complete insert/update/delete of child entities in this scenario using EF? Honestly, I expected more from EF.

推荐答案

这是一个棘手的问题。不幸的是,我不能提供你preFER解决方案。我不相信这是可能的。其中在网络环境中是不可能的 - 除非它们的实体检索的范围内作出的EF不能跟踪到您的实体进行的更改。这是唯一可行的办法是检索提问对象(范围内)在POST后/问题/编辑/ 1,并执行一个类型的合并张贴的问题之间,并且从检索到的问题数据库。这将包括对你QuestionModel分配的属性和使用您发布的QuestionModel数据库中检索每个QuestionChoiceModel。我会说,这不会是伟大实践要么,因为你会忘记包含的属性。它会发生。

This is a tough problem. Unfortunately, I cannot offer the solution that you prefer. I do not believe it is possible. EF cannot track changes made to your entities unless they are made within the context that the entities are retrieved - which is impossible in a web environment. The only way for this to be possible would be to retrieve the Question object (within a context) after the POST to /Questions/Edit/1, and to perform a type of "merge" between the POSTed Question, and the Question retrieved from the database. This would include assigning properties on your QuestionModel and each QuestionChoiceModel retrieved from the database using your POSTed QuestionModel. I will say that this wouldn't be great practice either, because you WILL forget to include a property. It will happen.

最好的(和最简单的)解决方案,我可以提供将添加/编辑使用上述.Entry()方法,你QuestionModel和QuestionChoiceModel(S)。你会牺牲最佳实践这里的解决方案,这将是不容易出错。

The best (and easiest) solution I can provide would be to add/edit your QuestionModel and QuestionChoiceModel(s) using the .Entry() method above. You will sacrifice "best practice" here for a solution that will be less error-prone.

QuestionModel questionFromDb;
QuestionModel questionFromPost;

QuestionModelChoice[] deletedChoices = questionFromDb.Choices.Where(c => !questionFromPost.Choices.Any(c2 => c2.Id == c.Id));


using (var db = new DbContext())
{
    db.Entry(questionFromPost).State = questionFromPost.Id == 0 ? EntityState.Added : EntityState.Modified;

    foreach(var choice in questionFromPost.Choices)
    {
        db.Entry(choice).State = choice.Id == 0 ? EntityState.Added : EntityState.Modified;
    }

    foreach(var deletedChoice in deletedChoices)
    {
        db.Entry(deletedChoice).State = EntityState.Deleted;
    }

    db.SaveChanges();
}

这篇关于完整的插入/更新/删除实体框架儿童实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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