【问题标题】:How to insert duplicated records in Entity Framework如何在实体框架中插入重复记录
【发布时间】:2016-05-31 16:17:52
【问题描述】:

关于插入重复记录,我遇到了非常奇怪的情况。 我正在根据某些标准检索记录,并且在修改了几个属性之后,我再次重新插入了整个对象集合,甚至没有更改对象的主键值。

但我没有得到预期的结果。我嵌套在父集合中的所有集合从未完全添加到数据库中。

我不知道,出了什么问题。我需要完全分离所有这些实体吗? 我已经在使用 NoTracking() 检索实体,甚至在修改其属性时分离父实体。

我的父集合是寄售并包含子实体作为列表“ConsignmentLine”

我的实体层次结构是:

public class Consignment 
{
    public int ConsignmentId { get; set; }
    public int ClientSubsidiaryId { get; set; }
    public int ForwarderId { get; set; }
    public int ClientId { get; set; } 

    public ICollection<ConsignmentLine> ConsignmentLines { get; set; }    

    public Consignment()
    {          
      ConsignmentLines = new List<ConsignmentLine>();            
    }
}

public class ConsignmentLine
{
    public int ConsignmentLineId { get; set; }
    public int PackagingId { get; set; }
    public double Amount { get; set; }
    public double Weight { get; set; }                

    public int ConsignmentId { get; set; }
    public virtual Consignment Consignment { get; set; }        
}

我的代码中涉及的步骤:

检索数据:

var Consignments = _dbContext.Consignments.AsNoTracking().Where(Pr => ( Pr.SourceParty == 0 && Pr.ParentId == null && Pr.ConnectState>=4 ) ).ToList();

修改几个属性。

consignments.ForEach(
            (consignment) =>
            {
                consignment.ClientId = clientId;                    
                _dbContext.Entry(consignment).State = System.Data.Entity.EntityState.Detached;
                consignment.ForwarderId = forwarderId;
                consignment.ClientSubsidiaryId = clientSubsidiaryId;                    
            }); 

尝试分块保存,因为我知道,寄售有 > 250000 条记录。

const int BulkSize = 1000;
var SkipSize = 0;

try
{                                                                                                                        
   while (SkipSize < consignments.Count)
   {
      ProcessableConsignments =   consignments.Skip(SkipSize).Take(BulkSize).ToList();                                                                                                                                                  _dbContext.Configuration.AutoDetectChangesEnabled = false;     
                                dbContext.Consignments.AddRange(ProcessableConsignments);

         var changedRecords = _dbContext.SaveChanges();
         SkipSize = SkipSize +  BulkSize;                                            
       }                                      
 }
 catch (Exception ex)
 {
    throw;
 }

我不知道我在这里缺少什么。 我只需要第二次将包含各种其他子实体的整个 BULK 记录作为集合重新插入(实际上是循环中的 N 次)作为新的 BULK。

【问题讨论】:

  • 如果你把这个去掉怎么办:_dbContext.Entry(consignment).State = System.Data.Entity.EntityState.Detached;
  • 您是否尝试设置 ConsignmentId = 0 ?
  • 真棒:以前我尝试过 ConsignmentId = -1,但这完全是修改和重置内部子实体(即 ConsignmentLines )并且重新初始化了 ConsignmentLines。所以,现在我懒得去碰ConsignmentId

标签: c# linq linq-to-entities entity-framework-6 bulkinsert


【解决方案1】:

我相信,当您从上下文中分离已经分离的实体时,您有效地指示上下文在将这些实体添加回上下文时忽略它们。 此外,出于性能原因,我强烈建议您不要在批量更新中使用 EF。至少为每个事务创建新的上下文,否则每个下一批的处理时间会增加。

【讨论】:

  • Vitaliy Kalinin :我不是在修改实体。我正在插入新实体。但我正在重新使用来自已检索实体的 99% 旧数据。这就是为什么我不想通过在内存中再次创建整个集合来制作带有嵌套子项的 220000 条记录的新副本。这就是原因,我只是用我提供的值修改了几个现有的字段。在插入这些实体(那些不是新创建的)之后,我期望 Entity 框架将它们作为新实体完全插入并返回给我新的主键。
  • 关于批量插入..我知道实体框架的这种限制。我打算用 EntityFramework.BulkInsert (CodePlex) 替换。但是现在我想使用这个实现。这就是为什么我要批量保存 1000 条记录的更改。
猜你喜欢
  • 2015-04-19
  • 1970-01-01
  • 2016-08-09
  • 2018-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-31
相关资源
最近更新 更多