【问题标题】:Updating Parent Entity doesn't Update Child Entity更新父实体不会更新子实体
【发布时间】:2013-06-03 08:24:32
【问题描述】:

是否再次将父实体附加到上下文并更新它应该更新子实体?我错过了什么吗?

或者我是否必须为子实体编写更新 EF 逻辑(在 DAL 中)?

这是我的示例代码模型:

ChildEntity entityChild;
if (ParentEntity.ChildEntity.SingleOrDefault() != null)
    entityChild = ParentEntity.ChildEntity.SingleOrDefault();
else
{
    entityChild = new ChildEntity();
    ParentEntity.ChildEntity.Add(entityChild);
}

entityChild.ColumnA= txtA.Text;
entityChild.ColumnB= txtB.Text;

// Send entityParent for update
_objParent.Update(entityParent)

_objParent.Update() 代码:

context.vouchers.Attach(entityParent);
ObjectStateEntry objectState = context.ObjectStateManager.GetObjectStateEntry(entityParent);
objectState.ChangeState(System.Data.EntityState.Modified);
context.SaveChanges();

更新(父加载代码示例)

    public ParentEntity GetById(int id)
    {
        using (var context = new DBEntities())
        {
            ParentEntity _entity = context.ParentEntity
                .Include("ChildEntity")
                .Where(e => e.parent_id == id);

            return (ParentEntity)_entity.SingleOrDefault()
        }
    }

【问题讨论】:

  • 您是否正在添加或更新父对象?如果您要更新对象,请告诉我们您是如何加载它的。
  • 参见上面已经提供的 _objParent.Update() 代码。 1) 附加实体,2) 获取 ObjectStateEntry,3) 修改状态,4) 将更改保存到上下文。
  • 如何加载父节点?
  • @RuiJarimba 哦,对不起,我误解了你。请看上面我已经添加了父加载代码。
  • ChangeState 只改变entityParent 的状态,而不是它的子对象。您还必须更改子对象的状态。

标签: c# entity-framework entity-framework-4


【解决方案1】:

EF 仅从它了解对象的那一点开始跟踪更改。在 EF 中使用更新的最简单方法是从数据库加载现有对象,对其进行更新,然后将其保存回来。在这种情况下,这意味着您应该从数据库中加载ParentEntity 对象。

另一种方法是像您一样使用Attach。在这种情况下,您应该首先调用附加未更改ParentEntity,然后调用ParentEntity.ChildEntity.Add(entityChild)

另一种选择是将新的ChildEntity 直接显式添加到DbContext,然后您可以简单地将ChildEntity 的外键值设置为ParentEntity 的键值以使它们连接。

【讨论】:

  • 我明白你的意思。我唯一不清楚的事情是确定是添加ChildEntity还是修改?由于 ParentEntity 在 UI 层中得到更改(添加/修改 ChildEntity),我必须设计一些技术来识别更改模式(添加/修改)。使用 ChildEntity 的 ModifiedBy 和 EnteredBy 属性来识别 chage 模式是否合适。 (即如果 ModifiedBy 为 null,则意味着这应该是一个 Add 操作)
  • 使用更改跟踪最简单的方法是加载ParentEntity 和所有相关的ChildEntities(在查询中使用Include(p => ChildEntities)),然后在执行@987654331 之前更新/添加子项@。在不加载 EF 的情况下进行保存通常比预期的要难。
【解决方案2】:

您应该在 using 语句中加载和更新您的实体 - 这样所有更改都将由实体框架跟踪:

using (var context = new DBEntities())
{
    // load and update entities
    // ....

    context.SaveChanges();
}

更新 - 这只是一个例子,我会保持简单。我会创建一个服务来放置我的逻辑 - 像这样:

public class ParentService
{
    // other service methods here

    protected DBEntities CreateContext()
    {
        return new DBEntities();
    }

    public ParentEntity Update(int id, string columnA, string columnB)
    {
        ParentEntity _entity = null;

        using (var context = CreateContext())
        {
            bool isNew = false;

            _entity = context.ParentEntity
                .Include("ChildEntity")
                .SingleOrDefault(e => e.parent_id == id);

            ChildEntity entityChild = ParentEntity.ChildEntity.SingleOrDefault();

            if(entityChild == null)
            {
                entityChild = new ChildEntity();
                isNew = true;
            }

            entityChild.ColumnA = columnA;
            entityChild.ColumnB = columnB;

            if(isNew)
            {
                ParentEntity.ChildEntity.Add(entityChild);
            }

            context.SaveChanges();
        }

        return _entity;
    }
}

在 UI 代码中:

string id = .....;
string columnA= txtA.Text;
strign columnB = txtB.Text;

var service = new ParentService();
ParentEntity parent = service.Update(id, columnA, columnB);

【讨论】:

  • 但问题是,实体通过应用层(DAL、BAL、UI)传递,因此与上下文分离。因此,您提供的样本需要在这方面进行大量更改。不是吗?
  • @Ali.NET:更新了我的答案。我的建议:创建一个包含所有逻辑和数据访问的服务层。 UI 将访问该服务,因此您不会将 UI 与其余部分混为一谈。
  • 我脑子里有这个逻辑。但是这样应用程序将两次访问服务器以更新实体。性能问题。
  • 抱歉,我不确定我是否理解您的意思 - 您已经访问了数据库 2 次...第一次加载实体,第二次更新它们。有什么区别?
  • 我的意思是,在您的更新服务方法中,您将访问服务器,首先,**获取子实体**,然后是 Context.SaveChanges。我想避免的额外打击。
猜你喜欢
  • 1970-01-01
  • 2019-12-05
  • 2013-07-24
  • 2016-11-16
  • 2011-12-19
  • 1970-01-01
  • 1970-01-01
  • 2021-02-09
  • 2015-01-26
相关资源
最近更新 更多