0

我有一个使用 Entity Framework Code First 定义的实体,它有一个可选的父节点字段。空父节点值意味着实体的节点位于根节点。同一父级下将有多个子级。

Class ContentDescriptor
{
    virtual ObjectId ParentObjectId{get;set;}
}

在数据库初始化程序中:

HasOptional(contentDescriptor => contentDescriptor.ParentObjectId).WithOptionalDependent()
    .Map(m => m.MapKey("ParentObjectId"));

导航属性分配如下:

  DBContext.ContentDescriptors.Add(contentDescriptor);
  contentDescriptor.ParentObjectId = ObjectIdFactory.Save(parent);

ObjectIdFactory.Save 检查 DBContext.ObjectId.Local 中是否有条目,然后检查 DBContext.ObjectId,如果内存或 DB 中没有记录,则进行插入并返回结果。

但是,当将新节点添加到上下文时,只有父节点的第一个子节点才能正确保存。第二个和以后的子级被添加到根,即使它们在本地显示为父级的子级。看起来框架在添加实体时无法为外键生成更新查询。

我的解决方法是在实体中公开外键并手动分配外键,但我想知道是否有更优雅的解决方案:

HasOptional(contentDescriptor => contentDescriptor.ParentObjectId).WithMany().
HasForeignKey(c=>c.ParentObjectIdRaw);
Property(c => c.ParentObjectIdRaw).HasColumnName("ParentObjectId");


contentDescriptor.ParentObjectIdRaw = contentDescriptor.ParentObjectId.ObjectIdId;
4

1 回答 1

0

这通常对我最有效(注意:我使用的是 4.3,我认为它应该没有太大不同,但不确定)......
(我使用伪Node作为自引用实体,所有其他和我想的一样)

public class Node
{
    public int NodeID { get; set; }
    public string Name { get; set; }
    public virtual Node Parent { get; set; }
    public virtual ICollection<Node> Children { get; set; }
}

...

modelBuilder.Entity<Node>()
    .HasOptional(n => n.Parent)
    .WithMany(n => n.Children);

...即您的实现问题可能WithOptionalDependent是通常是一对一的关系(如您所说,您有一对多)。

在使用方面...

using (var db = new UserDbContext())
{
    var root = new Node { Name = "root" };
    var node = new Node { Name = "first", Parent = root };
    var child1 = new Node { Name = "child1", Parent = node };
    var child2 = new Node { Name = "child2", Parent = node };
    db.Nodes.Add(child1);
    db.Nodes.Add(child2);
    db.SaveChanges();
    foreach (var n in db.Nodes.Include(x => x.Parent))
        Console.WriteLine("node: {0}, {1}, {2}, {3}, {4}", n.Name, n.NodeID, n.Parent != null ? n.Parent.Name : "", n.Parent != null ? n.Parent.NodeID : 0, n.Children != null ? n.Children.Count : 0);
}

...据我所知,您应该只添加子项(自动添加父项)。或者使用Children相反的方式添加,所以将子节点添加到父节点中,在这种情况下只保存根就足够了。

不确定这是否可以解决您所拥有的问题(我不确定您在ObjectIdFactory.Save后面做什么),但这是相同的模式,您不必真正拯救父母,之前只拯救一个孩子就足够了上SaveChanges()

希望这对任何人都有帮助

于 2012-04-22T23:16:43.030 回答