是否真的不可能更新EF中的小孩收藏(即使是非黑客方式)? [英] Is it really impossible to update child collection in EF out of the box (aka non-hacky way)?

查看:86
本文介绍了是否真的不可能更新EF中的小孩收藏(即使是非黑客方式)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设你的实体有这些课程。

Let's say you have these classes in your entities.

public class Parent
{
    public int ParentID { get; set; }
    public virtual ICollection<Child> Children { get; set; }
}

public class Child
{
    public int ChildID { get; set; }
    public int ParentID { get; set; }
    public virtual Parent Parent { get; set; }
}

你有一个用户界面来更新父母及其儿童,意思是如果用户添加新的 Child ,那么你必须插入,如果用户编辑现有的 Child ,那么需要更新,如果用户删除了一个 Child ,那么你必须删除。现在显然,如果您使用以下代码

And you have a user interface to update the Parent along with its Children, meaning if the user add new Child then you have to insert, if the user edits an existing Child then you need to update, and if the user removes a Child then you have to delete. Now obviously if you use the following code

public void Update(Parent obj)
{
    _parent.Attach(obj);
    _dbContext.Entry(obj).State = EntityState.Modified;
    _dbContext.SaveChanges();
}

它将无法检测 Child 因为EF无法检测导航属性中的更改。

it won't be able to detect the changes inside the Child because EF cannot detect changes inside a Navigation Property.

我一直在问这个问题4次,并得到混合的答案。那么事实上可以做到这一点吗?这个问题可以通过将 Parent Child 之间的用户界面进行分隔来解决问题,但我不想因为合并一个菜单中的 Child Parent 在业务应用程序开发中非常常见,而且更加用户友好。

I've been asking this question for like 4 times and get mixed answers. So is it actually possible to do this stuff without it getting complicated? This problem can fix the problem by separating the user interface between Parent and Child but I don't want to because merging both Child and Parent in one menu is pretty common in business application development and more user friendly.

更新:
我正在尝试下面的解决方案,但它不起作用。

public ActionResult(ParentViewModel model)
{
    var parentFromDB = context.Parent.Get(model.ParentID);

    if (parentFromDB != null)
    {
        parentFromDB.Childs = model.Childs;
    }

    context.SaveChanges();
}

除了检测孩子内的变化,EF将无法告诉怎么办老孩子例如,如果 parentFromDB 有3个孩子,那么我第一次从DB中删除它,然后删除第2个和第3个孩子。然后我得到关系无法更改,因为一个或多个外键属性在保存时不可为空。

Instead of detecting changes inside the Children, EF won't be able to tell what to do with old child. For example if parentFromDB has 3 children the first time I pull it from DB then I delete the 2nd and 3rd child. Then I'm getting The relationship could not be changed because one or more of the foreign-key properties is non-nullable when saving.

我相信这是发生了什么:
无法更改关系,因为一个或多个外键属性不可为空

I believe this is what happened : The relationship could not be changed because one or more of the foreign-key properties is non-nullable

这让我回到正方形,因为在我的情况下,我不能从数据库中获取并更新该条目并调用 SaveChanges

Which took me back to square one because in my scenario, I can't just fetch from the DB and update the entry and call SaveChanges.

推荐答案


因为EF无法检测导航属性内的更改

because EF cannot detect changes inside Navigation Property

这似乎是一个有点扭曲的描述: _dbContext.Entry(obj).State = EntityState.Modified 不会修改导航属性。

This seems to be a somewhat distorted description of the fact that _dbContext.Entry(obj).State = EntityState.Modified doesn't mark navigaton properties as modified.

of c我们的EF跟踪导航属性的变化。它跟踪附加到上下文的所有实体的属性和关联的更改。因此,您的问题的答案,现在肯定地说...

Of course EF tracks changes in navigation properties. It tracks changes in properties and associations of all entities that are attached to a context. Therefore, the answer to your question, now positively stated...


是否可以更新EF中的子集合开箱即用

Is it possible to update child collection in EF out of the box

...是:

唯一的事情是:你不要这样做

The only thing is: you don't do it out of the box.

out of更新任何实体的方框,无论是某个集合中的父项还是子节点都是:

The "out of the box" way to update any entity, whether it be a parent or a child in some collection is:


  • 从数据库中获取实体。

  • 修改其属性或添加/删除元素到其集合

  • 调用 SaveChanges()

  • Fetch entities from the database.
  • Modify their properties or add/remove elements to their collections
  • Call SaveChanges().

就是这样。 Ef跟踪更改,您从未设置实体状态 s。

That's all. Ef tracks the changes and you never set entity States explicitly.

但是,在断开连接(n层)情景,这变得越来越复杂。我们对实体进行序列化和反序列化,所以不能有跟踪其变化的任何上下文。如果我们想把这些实体存储在数据库中,现在我们的任务是让EF知道这些变化。基本上有两种方法:

However, in a disconnected (n-tier) scenario, this gets more complicated. We serialize and deserialize entities, so there can't be any context that tracks their changes. If we want to store the entities in the database, now it's our task to make EF know the changes. There are basically two ways to do this:


  • 根据我们对实体的了解,手动设置状态(如:主键> 0表示它们存在并应更新)

  • 绘制状态:从数据库中检索实体,并重新应用从反序列化实体到他们。

  • Set the states manually, based on what we know about the entities (like: a primary key > 0 means that they exist and should be updated)
  • Paint the state: retrieve the entities from the database and re-apply the changes from the deserialized entities to them.

当涉及到关联时,我们总是必须绘制状态。我们必须从数据库中获取当前的实体,并确定添加/删除哪些子项。没有办法从反序列化的对象图本身推断出这一点。

When it comes to associations, we always have to paint the state. We have to get the current entities from the database and determine which children were added/deleted. There's no way to infer this from the deserialized object graph itself.

有各种各样的方法可以减轻这种无聊和精心制作的绘画状态的任务,但这超出了这个范围Q&安培; A。一些参考资料:

There various ways to alleviate this boring and elaborate task of painting the state, but that's beyond the scope of this Q&A. Some references:

  • Generic repository to update an entire aggregate
  • GraphDiff

这篇关于是否真的不可能更新EF中的小孩收藏(即使是非黑客方式)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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