【问题标题】:how to insert parent child while doing entityframework.bulkinsert?如何在进行 entityframework.bulkinsert 时插入父子?
【发布时间】:2015-01-06 16:07:01
【问题描述】:

我正在使用 Entityframework 6,我正在尝试在数据库中插入一种父子类型的数据。 我正在使用 Entityframework.BulkInsert 插入数据。我在所有表中都有 autoIncrement int 主键

我的对象如下:

    var parentObjects= new List<parentObject>();            
    var childObjects= new List<childObject>();

        for (int i = 0; i <= 100; i++)
        {
            var parentObj= new parentObject()
            {
                Name="p1",
                Address="a1"
            };

childObjects= SeedInitializer.ChildItems.OrderBy(x => new Random().Next()).Take(2).ToList();//this gets 2 child objects
            foreach (var childObj in childObjects)
            {
                childObj .ParentObject= parentObj;
                //childObj .CommissionPlanId = i;   //tried this still not working
                parentObj.ChildObjects.Add(childObj );                                     
            }
            parentObjects.Add(parentObj);
        }
        //when I do a quickwatch on parentObjects, i see child objects in each parentObject, but                  
        //with the last id of parentObject
        context.BulkInsert(parentObjects, 1000);
        context.SaveChanges();

在保存时仅在 childObject 中创建了 2 条记录,创建的 parentObject id 错误,即 0 我无法理解为什么没有创建子项目,而创建了父对象。有人可以帮助我了解我在哪里做错了吗?

【问题讨论】:

标签: entity-framework entity-framework-4 entity-framework-5 entity entity-framework-6


【解决方案1】:

我不认为有一个简单的方法来完成这个任务,因为为了插入孩子,你必须真正完成插入父母并获得他们的 id。普通的 EF 插入的优点是每个 INSERT 还将嵌入一个 SELECT 来获取刚刚生成的标识符,以便它可以将其推送给孩子(如果有的话)。

一种可能的解决方案如下:

  1. Guid RefProperty 添加到同样持久化的ParentObject 类型
  2. Guid BatchId 添加到同样持久化的ParentObject 类型
  3. Guid RefProperty 添加到未持久化的ChildObject 类型
  4. 使用以下(主要是伪代码)序列保存整个结构

    var batchId = new Guid();
    parentObjects.ForEach(item => item.BatchId = batchId);
    
    // set RefProperty for all parents and children to reflect proper parentation 
    
    TransactionScope scope = null;
    try
    {
         context.BulkInsert(parentObjects, 1000);
         var newParents = context.ParentObjects.Where(_ => _.BatchId = batchId);
         var refPropMap = newParents.ToDictionary(_ => _.RefProperty, _ => ParentId);
         var childObjects.ForEach(item => item.ParentId = refPropMap[item.RefProperty]);
         context.BulkInsert(childObjects, 1000);
    
         DataAccess.SaveChanges();
         scope.Complete();
    }
    catch (Exception exc)
    {
         scope?.Dispose();
    }
    

注意:这未经测试

这很丑陋,但它应该可以解决问题:尽量减少到 SQL Server 的往返行程,并且仍然是一个单一的事务。

为了使SELECT 更快,ParentObject 表上的索引应该放在BatchId 上,包括(覆盖)它的键。

替代方案:将这些表的设计更改为不使用自动增量,而是使用UNIQUEIDENTIFIER 列。这样,可以在插入之前设置所有标识符。

【讨论】:

    【解决方案2】:

    免责声明:我是EntityFramework.BulkInsert的所有者

    你不能。

    此功能从未实现过。

    免责声明:我是Entity Framework Extensions的所有者

    但是,这个新的库(不是免费的),可以轻松处理这种情况。

    BulkSaveChanges 的工作方式与 SaveChanges(处理父/子)完全相同,但速度更快!

    支持所有方法:

    • 批量保存更改
    • 批量插入
    • 批量删除
    • 批量更新
    • 批量合并

    例子

    // Easy to use
    context.BulkSaveChanges();
    
    // Easy to customize
    context.BulkSaveChanges(bulk => bulk.BatchSize = 100);
    

    【讨论】:

      猜你喜欢
      • 2014-10-20
      • 2014-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多