代码之家  ›  专栏  ›  技术社区  ›  bitshift

更新由多层实体表示的树结构的设计模式或算法

  •  0
  • bitshift  · 技术社区  · 7 年前

    有一个例子,我的目标表有几个FK相关的“层”。

    Root
        |__A
            |__B
                |__C
                    |__D
    

    我从一个平面文件导入一些数据,将结果投影到一组非常相似的POCO对象中。从那里我需要从这些POCO对象中选择并进入实体。问题是如何最好地更新实体,因为每个级别可以是新的,或者已经存在并且需要更新。

    类似地,根可能和A一样存在,但不是它的依赖B。 每个级别都有需要更新的特定字段(如果它们已经存在)。

    1 回复  |  直到 7 年前
        1
  •  0
  •   Harald Coppoolse    7 年前

    你的数据库

    在实体框架中,您将拥有以下内容:

    class Root
    {
        public int Id {get; set;}
        ... // other properties
    
        // every Root has zero or more As (one-to-many):
        public virtual ICollection<A> As {get; set;}
    }
    class A
    {
        public int Id {get; set;}
        ... // other properties
    
        // every A belongs to exactly one Root, using foreign key
        public int RootId {get; set;}
        public virtual Root Root {get; set;}
    
        // every A has zero or more Bs:
        public virtual ICollection<B> Bs {get; set;}
    }
     class B
    {
        public int Id {get; set;}
        ... // other properties
    
        // every B belongs to exactly one A, using foreign key
        public int AId {get; set;}
        public virtual A A {get; set;}
    
        // every B has zero or more Cs:
        public virtual ICollection<C> Cs {get; set;}
    }
    etc.
    

    在实体框架中,表的列由非虚拟属性表示。虚拟属性表示表之间的关系(一对多,多对多)

    你的档案

    您提到可能是您已经从文件中读取了Root1,并再次与其他子级一起读取Root1。你的文件似乎是平的:

    Root1, A1, B1, ...
    Root1, A1, B2, ...
    Root1, A2, B3, ...
    Root2, A3, B4, ...
    Root1, A4, B5, ...
    

    class Line
    {
        public Root Root {get; set;}
        public A A {get; set;}
        public B B {get; set;}
        ...
    }
    
    IEnumerable<Line> ReadLines(...) {...}
    

    填充数据库

    void FillDatabase(IEnumerable<Line> lines)
    {
        // convert the lines into a sequence or Roots with their As,
        // with their Bs, with their Cs, ...
        IEnumerable<Root> roots = lines.GroupBy(line => line.Root,
            (root, linesOfThisRoot) => new Root
            {
                Name = root.Name,
                ... other root properties
                As = linesOfThisRoot.GroupBy(line => line.A,
                (a, linesWithRootAndA) => new A
                {
                    Name = a.Name,
                    ... other a properties
                    Bs = linesWithRootAndA.GroupBy(line => line.B,
                         (b, linesWithRootAB) => new B
                         {
                            ... B properties
                            Cs = linesWithRootAB.GroupBy(line => line.C,
                            {
                               etc.
                            })
                            .ToList(),
                        })
                        .ToList(),
                   })
                   .ToList(),
                })
                .ToList();
            });
        using (var dbContext = new MyDbContext()
        {        
            dbContext.Roots.AddRange(roots.ToList());
            dbContext.SaveChanges();
        }
    }
    
    推荐文章