【问题标题】:Updating Entity with child and grandchild entities使用子实体和孙实体更新实体
【发布时间】:2015-11-22 21:00:36
【问题描述】:

我尝试在更新具有深厚关系的实体时找到问题的最佳解决方案。因为我的实体太复杂,关系更深,我简化成这个。

MainCategory - Category 是一对多的关系,Category - SubCategory 也是一对多的关系

public class MainCategory
{
    [Key]
    public int Id { get; set; }
    public string MainCategoryName { get; set; }

    public virtual ICollection<Category> Categories { get; set; }
}

public class Category
{
    [Key]
    public int Id { get; set; }
    public string CategoryName { get; set; }

    public virtual ICollection<SubCategory> SubCategories { get; set; }
}

public class SubCategory 
{
    [Key]
    public int Id { get; set; }
    public string SubCategoryName { get; set; }

    public Category Category { get; set; }
}

这是我在更新或带有子孙记录的新 MainCategory 实体来自某个地方时处理这种情况的方法。

public void AddOrUpdateMainCategory()
{
    using (var ctx = new MyContext())
    {
        // Gets MainCategory domain object.
        // Domain object has no id property because it does not come from (ctx.MainCategories)
        var mainCategory = GetMainCategory();

        var mainCategoryFromDb = ctx.MainCategory.Include(x => x.Categories.Select(y => y.SubCategories)).FirstOrDefault(x => someCondition());

        if (mainCategoryFromDb == null)
        {
            ctx.ShopParameterPeriodItems.Add(mainCategory);
        }

        // If mainCategoryFromDb is not null, mainCategory object should map to mainCategoryFromDb.
        else
        {
            ctx.SubCategories.RemoveRange(mainCategoryFromDb.Categories.SelectMany(x => x.SubCategories));
            ctx.Categories.RemoveRange(mainCategoryFromDb.Categories);
            ctx.MainCategories.Remove(mainCategoryFromDb);

            ctx.MainCategories.Add(mainCategory);
         }

         ctx.SaveChanges();
    }
}

代码问题

  • 由于更新机制是删除旧实体及其子实体和孙实体并添加新实体,因此每次都会刷新数据库记录的Id值。如果 MainCategoryCategorySubCategory 存在来自不同表的任何外键,这将是一个大问题。
  • 第一个问题可以这样解决

        foreach (var category in mainCategoryFromDb.Categories)
        {
             foreach (var subCategory in category.SubCategories)
             {
                  // Set subCategory properties
             }
    
             // Set category properties
        }
    
        // Set mainCategoryFromDb properties
    

    这解决了 Id loss 问题,但正如我所写,实体非常复杂。这将很难维护,例如,我们不知道 ma​​inCategory 的哪个类别会更新 ma​​inCategoryFromDb 的类别,因为 mainCategory 及其子实体和孙子实体没有 Id属性。

我正在寻找的是解决问题的方法。

【问题讨论】:

    标签: entity-framework entity-framework-5 entity-framework-6


    【解决方案1】:

    您的问题是您正在使用断开连接的实体,因此DbContext 不会监控它们的更改。因此,您需要做的是在断开连接的场景中自己跟踪更改,稍后,当您将它们附加回DbContext 时,根据跟踪的更改为每个实体设置正确的状态。

    有一个跟踪更改的 fiex 解决方案,但是,要将更改发送到数据库,您只需将根对象附加到上下文,然后设置每个跟踪实体的状态。

    请参阅How to use DBContext.Add/Attach (using EF CodeFirst 4.1) with nested opbjects。这显示了附加和设置状态的基本方式。然后您只需设置不同的状态,除了本问答中显示的Unchanged

    【讨论】:

    • 但我认为,要附加的实体必须是一个 id 属性才能与数据库记录匹配?我的 DTO 对象没有。
    猜你喜欢
    • 2016-11-16
    • 1970-01-01
    • 2019-02-09
    • 2019-12-05
    • 1970-01-01
    • 2011-12-19
    • 1970-01-01
    • 2013-07-24
    • 2011-12-10
    相关资源
    最近更新 更多