0

オプションの親ノード フィールドを持つ Entity Framework Code First を使用して定義されたエンティティがあります。null 親ノード値は、エンティティのノードがルートにあることを意味します。同じ親の下に複数の子が存在します。

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

DB イニシャライザで:

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 にレコードがない場合は、挿入を実行して結果を返します。

ただし、新しいノードがコンテキストに追加されると、親の最初の子のみが正しく保存されます。2 番目以降の子は、ローカルで親の子として表示される場合でも、ルートに追加されます。エンティティが追加されているときに、フレームワークが外部キーの更新クエリを生成できないようです。

私の回避策は、エンティティで外部キーを公開し、外部キーを手動で割り当てることですが、より洗練された解決策があるかどうか疑問に思っています。

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は、通常は1対1の関係である可能性があります(あなたが言ったように、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()

これが何かに役立つことを願っています

于 2012-04-22T23:16:43.030 に答える