2016-05-31 79 views
0

我在插入重复记录时遇到了非常奇怪的情况。 我正在根据特定条件检索记录,并且在修改了几个属性之后,我再次重新插入整个对象集合,甚至不更改对象的主键值。如何在实体框架中插入重复记录

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

我不知道怎么回事。我是否需要完全分离所有这些实体? 我已经使用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。

+0

如果你将删除这个:_dbContext.Entry(寄存).State = System.Data.Entity.EntityState.Detached; –

+1

你是否尝试设置ConsignmentId = 0? –

+0

太棒了:以前我在尝试ConsignmentId = -1,但这是完全修改和重置内部子实体(即ConsignmentLines)和ConsignmentLines重新初始化。 所以,现在我没有费心触摸ConsignmentId – Usman

回答

0

我相信,当您将已分离的实体从上下文中分离出来时,您可以有效地指示上下文在添加回上下文时忽略这些实体。 此外,我强烈建议您不要因性能原因而在批量更新中使用EF。在其他情况下,至少为每个交易创建新的上下文,每个下一批次的处理时间将会增长。

+0

Vitaliy Kalinin:我没有修改实体。我正在插入新的实体。但是我重新使用了已经检索到的实体的99%的旧数据。这就是为什么我不想通过在内存中再次创建整个集合来制作带有嵌套子节点的220000条记录的新副本。这就是原因,我只是用我提供的值修改了几个退出的字段。在插入这些实体(那些不是新创建的)之后,我希望实体框架将它们全部插入为新实体,并将返回新的主键。 – Usman

+0

关于批量插入..我知道实体框架的这种限制。我打算用EntityFramework.BulkInsert(CodePlex)替换。但是现在我想继续这个实现。 这就是为什么我只保存1000个记录的批量修改。 – Usman