实体框架中多个记录的插入顺序 [英] Insertion order of multiple records in Entity Framework

查看:91
本文介绍了实体框架中多个记录的插入顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我尝试一次添加一个包含多个孩子的实体时,我遇到EF重新排序插入的麻烦。我有一个3级结构,每一个之间有一对多关系(外部1 - *项目1 - *子项目)。如果我尝试插入一个新的外部项目和子项目,包含子项目的项目最终被插入。



示例代码(.NET 4.5,EF 5.0.0 -rc):

  public class Outer 
{
public int OuterId {get;组; }
public virtual IList< Item>物品{get;组;
}

public class Item
{
public int OuterId {get;组; }
[ForeignKey(OuterId)]
public virtual Outer Outer {get;组; }

public int ItemId {get;组; }
public int Number {get;组; }

public virtual IList< SubItem>子项{get;组;
}

public class SubItem
{
public int SubItemId {get;组; }

[ForeignKey(ItemId)]
public virtual Item Item {get;组; }
public int ItemId {get;组; }
}

public class MyContext:DbContext
{
public DbSet< Outer>外人{get;组; }
public DbSet< Item>物品{get;组; }
public DbSet< SubItem>子项{get;组;


$ Program
{
static void Main(string [] args)
{
Database.SetInitializer(new DropCreateDatabaseAlways& MyContext>());
MyContext context = new MyContext();

//添加一个外部对象,其中3个项目,中间有一个子项
外部外部1 =新的外部{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();

//打印最终在
foreach(context.Items中的项目项目)
{
Console.WriteLine({0} \ t {1},item.ItemId,item.Number);
}
//生成输出:
// 1 2
// 2 1
// 3 3
}
} $ b我知道指出,为了满足关系约束,插入可能需要重新排序,但这不是问题。他的回答还提到他们无法跟踪订单保存结构中的项目顺序,例如列表。



我想知道的是如何获得这些插件要订购。虽然我可以依靠通过PK以外的其他字段来排序我的插入项目,但是如果我可以依靠PK订单,效率会更高。我真的不想使用多个SaveChanges调用来实现这一点。



我使用的是EF5 RC,但是根据其他未回答的问题,已经有一段时间了!

解决方案


我想知道的是我能得到什么这些插入要被订购。


你不能。数据库命令的顺序是EF的内部行为。如果要控制命令的顺序不要使用从低级数据库交互中抽象出的工具 - 直接使用SQL。



根据评论编辑:



是的,这是低级别的互动,因为你期待的顺序是使用抽象处理SQL命令时,您无法控制。在高层次上,你会得到不同的东西,因为你正在使用不符合这种抽象的期望。如果要控制SQL命令的顺序,您必须通过一个一个地保存项目来强制EF(=>多个 SaveChanges TransactionScope )或自己写SQL。否则使用单独的列进行排序。



Btw。 EF不会按照您的看法保存实体。它有自己的更改跟踪器,保留对所有附加实例的引用。参考文献保存在多个字典实例和字典不保留插入顺序。如果这些集合用于生成SQL命令(我猜是这样)就不能保证任何顺序。


I'm having trouble with EF reordering my inserts when I try and add an entity with multiple children all at once. I've got a 3 level structure with one-to-many relationships between each (Outer 1--* Item 1--* SubItem). If I try and insert a new Outer with Items and Subitems, the Items which contain SubItems end up being inserted first.

Sample Code (.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
    }
}

I'm aware of this answer by Alex James which states that inserts may need to be reordered in order to satisfy relational constraints, but that is not the issue here. His answer also mentions that they can't track the order of items in order-preserving structures such as Lists.

What I'd like to know is how I can get these inserts to be ordered. While I can rely on sorting my inserted items by a field other than the PK, it's a lot more efficient if I can rely on the PK order. I don't really want to have to use multiple SaveChanges calls to accomplish this.

I'm using EF5 RC, but judging by the other unanswered questions around, this has been around for some time!

解决方案

What I'd like to know is how I can get these inserts to be ordered.

You cannot. Order of database commands is EF's internal behavior. If you want to control the order of commands don't use tools which abstract you from low level database interactions - use SQL directly.

Edit based on comment:

Yes it is low level interaction because you are putting expectations on the order of SQL commands when working with abstraction you don't have under your control. At high level you are getting something different because you are using expectations which don't work with that abstraction. If you want to have control over order of SQL commands you must either force EF by saving items one by one (=> multiple SaveChanges and TransactionScope) or write SQL yourselves. Otherwise use separate column for ordering.

Btw. EF doesn't save the entity as you see it. It has its own change tracker holding references to all your attached instances. References are held in multiple Dictionary instances and dictionary doesn't preserve insertion order. If these collections are used for generating SQL commands (and I guess they are) no order can be guaranteed.

这篇关于实体框架中多个记录的插入顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆