在某些情况下,我的目标表具有与FK相关的几个“层”。
Root
|__A
|__B
|__C
|__D
我正在从平面文件导入一些数据,并将结果投影到一组非常相似的POCO对象中。从那里,我需要从这些POCO对象中选择并进入实体。问题是,鉴于每个级别可以是新的或已经存在并且需要更新,因此如何最好地更新实体。
例如,根对象本身可能已经创建,但是不包含A,因此必须先创建A,然后添加其从属对象。
类似地,根可能已经和A一样存在,但不存在依赖的B。 每个级别都有特定的字段,如果它们已经存在,则需要更新。
答案 0 :(得分:0)
我假设您的层中存在一对多关系:每个根都有零个或多个As,每个A使用外键完全属于一个根。每个A都有零个或多个B,每个B都使用外键等恰好属于一个A。
在实体框架中,您将拥有类似的东西:
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();
}
}