2016-05-31 13 views
0

重複したレコードの挿入に関して非常に奇妙な状況があります。 特定の条件に対してレコードを取得していますが、いくつかのプロパティを変更した後、オブジェクトのプライマリキー値を変更しなくても、オブジェクトのコレクション全体を再度挿入します。Entity Frameworkで重複レコードを挿入する方法

しかし、私は期待された結果を得ていません。親コレクション内にネストされたすべてのコレクションは、データベースに完全に追加されませんでした。

私は何が間違っているのか分かりません。これらのエンティティをすべて完全に切り離す必要がありますか? 私はすでに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(); 

複数のプロパティを変更しています。

私が知っているので、チャンクに保存しようとすると、> 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として、他のさまざまな子エンティティを含むレコードのBULK全体を2回目のコレクション(実際にはN回ループ)として再挿入する必要があります。

+0

このファイルを削除するとどうなりますか?_dbContext.Entry(consignment).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

関連する問題