更改外键首先对EF4代码没有影响

时间:2012-04-22 15:38:21

标签: entity-framework-4.1 ef-code-first

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

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

在DB Initializer中:

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,如果内存或数据库中没有记录,则执行插入并返回结果。

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

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

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


contentDescriptor.ParentObjectIdRaw = contentDescriptor.ParentObjectId.ObjectIdId;

1 个答案:

答案 0 :(得分: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,通常是一对一的关系(如您所说,您有1对多)。

在使用方面......

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()

之前保存一个孩子就足够了

希望这有助于任何