【问题标题】:Updating Child Entities in Entity Framework MVC在实体框架 MVC 中更新子实体
【发布时间】:2014-09-07 12:28:33
【问题描述】:

我在我的视图中显示父实体及其子实体,并让用户能够编辑父实体和子实体。

当用户点击保存时。父实体仅被修改,而子实体被忽略。我的解决方法是这样的。

var addressRepo=_dataRepositoryFactory.GetDataRepository<IPatientAddressRepository>();
foreach (var address in entity.Addresses)
{
    addressRepo.Update(address);
}

_dataRepositoryFactory.GetDataRepository<IPatientContactRepository>().Update(entity.Contact);


var guardianRepo = _dataRepositoryFactory.GetDataRepository<IPatientGuardianRepository>();
foreach (var guardian in entity.Guardians)
{
    guardianRepo.Update(guardian);
}

_dataRepositoryFactory.GetDataRepository<IPatientDemographicRepository>().Update(entity.Demographic);

return _patientRepository.Update(entity);

有没有更好的方法来更新所有子实体?

【问题讨论】:

  • 请分享您的 Patient 类定义和您的 IPatientRepository 实现。

标签: asp.net-mvc entity-framework


【解决方案1】:

对断开连接的实体应用更新时的标准模式如下:

  1. 将根实体附加到上下文以启用跨图表的更改跟踪
  2. 这会将整个对象图标记为EntityState.Unchanged,因此您需要遍历图并相应地设置状态
  3. 将父实体标记为EntityState.Modified,以便保留其更改
  4. 对于每个子实体,计算出更改的性质(插入、删除或更新)并相应地标记其状态
  5. 保存上下文后,整个图表的更改将被保留。

采用这种方法意味着您可以将依赖项需求减少到根实体的单个存储库。

例如,假设您只处理更新:

using (var context = new MyContext())
{
    context.attach(parentEntity);
    context.Entry(parentEntity).State = EntityState.Modified;

    context.Entity(parentEntity.ChildEntity1).State = EntityState.Modified;
    context.Entity(parentEntity.ChildEntity2).State = EntityState.Modidied;

    context.SaveChanges();
}

这通常封装在存储库上的 AttachAsModified 方法中,该方法知道如何根据图的根实体“绘制对象图的状态”。

例如

public class MyRepository<TEntity>
{
    public void AttachAsModified(TEntity entity)
    {
        _context.attach(entity);
        _context.Entry(entity).State = EntityState.Modifed;
        _context.Entity(entity.ChildEntity1).State = EntityState.Modified;
        // etc
        _context.SaveChanges();
    }   
}

如果您需要考虑插入或删除子实体,则会有额外的复杂性。这些归结为加载根实体及其子实体的当前状态,然后将子集与更新的根实体上的集进行比较。然后根据集合的重叠将状态设置为EntityState.DeletedEntityState.Added

NB 代码直接输入浏览器,因此可能/将会出现一些拼写错误。

【讨论】:

  • EF6 不再存在此解决方案“context.attach”不存在...有什么建议吗?
  • 可能的解决方案:T dbEntity = await Get(entity.Id);条目(dbEntity).UpdateFrom(实体);保存更改(); ...未经测试。
【解决方案2】:

我记得在一次更新父母和孩子时遇到了类似的问题。我并没有真正花时间找出确切的原因,但我很快意识到将大量模型传回并进行大量更改可能不是最好的模型。在一种极端情况下,我的帖子太大了,超出了默认消息大小。

像这样更新大型父/子模型的首选方法是将整个父/子模型向下传递到页面,然后通过 ajax 分别更新每个子模型。所以父母和孩子永远不会在同一个动作中更新。它还使处理错误更容易,如果您向上传递一个庞大的模型并且一个孩子未能通过验证,那么有时很难以对用户显而易见的方式将该错误传递回集合等中。而进行单次更新总是更容易让用户发现/处理。

我会敦促您使用视图模型而不是直接将实体传递到您的视图中,除了最简单的视图之外,这被认为是不好的做法。您可以精简您的模型以减少视图的负载,您还可以在未来轻松扩展您的视图模型以添加额外的功能,而不会影响您的实体。

只是一些想法,希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多