複数の子を持つエンティティを一度に追加しようとすると、EF が挿入を並べ替えるのに問題があります。それぞれの間に 1 対多の関係を持つ 3 レベルの構造があります ( Outer 1--* Item 1--* SubItem
)。アイテムとサブアイテムを含む新しいアウターを挿入しようとすると、サブアイテムを含むアイテムが最初に挿入されます。
サンプル コード (.NET 4.5、EF 5.0.0-rc):
public class Outer
{
public int OuterId { get; set; }
public virtual IList<Item> Items { get; set; }
}
public class Item
{
public int OuterId { get; set; }
[ForeignKey("OuterId")]
public virtual Outer Outer { get; set; }
public int ItemId { get; set; }
public int Number { get; set; }
public virtual IList<SubItem> SubItems { get; set; }
}
public class SubItem
{
public int SubItemId { get; set; }
[ForeignKey("ItemId")]
public virtual Item Item { get; set; }
public int ItemId { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Outer> Outers { get; set; }
public DbSet<Item> Items { get; set; }
public DbSet<SubItem> SubItems { get; set; }
}
class Program
{
static void Main(string[] args)
{
Database.SetInitializer(new DropCreateDatabaseAlways<MyContext>());
MyContext context = new MyContext();
// Add an Outer object, with 3 Items, the middle one having a subitem
Outer outer1 = new Outer { Items = new List<Item>() };
context.Outers.Add(outer1);
outer1.Items.Add(new Item { Number = 1, SubItems = new List<SubItem>() });
outer1.Items.Add(new Item { Number = 2, SubItems = new List<SubItem>(new SubItem[] { new SubItem() }) });
outer1.Items.Add(new Item { Number = 3, SubItems = new List<SubItem>() });
context.SaveChanges();
// Print the order these have ended up in
foreach (Item item in context.Items)
{
Console.WriteLine("{0}\t{1}", item.ItemId, item.Number);
}
// Produces output:
// 1 2
// 2 1
// 3 3
}
}
リレーショナル制約を満たすために挿入を並べ替える必要があるかもしれないと述べているAlex James によるこの回答を認識していますが、それはここでは問題ではありません。彼の答えは、リストなどの順序を維持する構造ではアイテムの順序を追跡できないことにも言及しています。
私が知りたいのは、これらのインサートを注文する方法です。挿入したアイテムを PK 以外のフィールドでソートすることもできますが、PK 順序に頼ることができれば、はるかに効率的です。これを達成するために複数の SaveChanges 呼び出しを使用する必要はありません。
私は EF5 RC を使用していますが、他の未回答の質問から判断すると、これはしばらく前から存在しています。