2016-03-21 13 views
-1

私はProductStatisticsテーブルにProductStatisticsTempテーブルのデータをコピーしようとしているを使用して、一つ一つ、挿入複数のレコードLINQ

var str = from a in db.ProductStatisticsTemp select a; 

ProductStatistics ls = new ProductStatistics(); 

foreach (var val in str.ToList()) 
{      
    ls.Product_ID = val.Product_ID; 
    ls.ProductNameEn = val.ProductNameEn; 
    ls.ProductNameAr = val.ProductNameAr; 

    db.ProductStatistics.Add(ls); 
    db.SaveChanges(); 
} 

最初のレコードを挿入することができますが、その試み一度取得中にエラー

次第二1を挿入します

プロパティ 'Product_ID'はオブジェクトのキー情報の一部であり、 は変更できません。

+4

'ProductStatistics ls = new ProductStatistics();'をループ内に移動する必要があります(ループの後に 'db.SaveChanges();'を移動できます)。 –

+0

同じオブジェクトを使用する場合は、そのすべてのプロパティを –

答えて

2

オブジェクトのインスタンスが1つあり、既に追加されたオブジェクトを2回追加しようとしているからです。

ループ内に新しいオブジェクトProductStatisticsを作成する必要があります。

また、あなたは一度だけトリガーDB通信することにより、パフォーマンスを改善するために、ループの後に一度だけ、変更を保存することができます:ここで

var str = from a in db.ProductStatisticsTemp select a; 

foreach (var val in str.ToList()) 
{      
    ProductStatistics ls = new ProductStatistics 
    { 
     Product_ID = val.Product_ID, 
     ProductNameEn = val.ProductNameEn, 
     ProductNameAr = val.ProductNameAr 
    }; 

    db.ProductStatistics.Add(ls); 
} 

db.SaveChanges(); 
+0

にリセットする必要がありますが、行単位でデータを一度に保存する方法はありませんか? – kez

+0

@kez主な質問は:理由は何ですか?ループ内でSaveChangesを呼び出すことはできますが、結果は同じになり、通信チャネルに余分な負荷がかかります。 –

+0

ループ内に 'SaveChanges'を挿入しましたエラーが発生しました'プロバイダ接続でトランザクションを開始中にエラーが発生しました。詳細は内側の例外を参照してください。 – kez

1

は若干異なる方法です。

var products = db.ProductStatisticsTemp.Select(t => new ProductStatistics 
          { 
           Product_ID = t.Product_ID, 
           ProductNameEn = t.ProductNameEn, 
           ProductNameAr = t.ProductNameAr 
          }).ToList() 

db.ProductStatistics.AddRange(products); 
db.SaveChanges();  
0

私見@Vadimマルティノフからインスパイア

Product_IDは、プライマリキー、およびデータベースから キーをインクリメントするためにあなたのセットである場合。これをしないでくださいProduct_ID = val.Product_ID。 キーはデータベースから生成する必要があります。変更を保存した後にID が表示されます。唯一EF6からサポートdocumentation

を参照してください

try 
{ 
    var str = from a in db.ProductStatisticsTemp select a; 

    //This will improve some performance 
    db.Configuration.AutoDetectChangesEnabled = false; 

    foreach (var val in str.ToList()) 
    {      
     ProductStatistics ls = new ProductStatistics 
     { 

     Product_ID = val.Product_ID, 
     ProductNameEn = val.ProductNameEn, 
     ProductNameAr = val.ProductNameAr 
    }; 

    //use AddRange or Add based on your EF Version. 
    db.ProductStatistics.Add(ls); 
    } 

    db.SaveChanges(); 
} 
finally 
{ 
     db.Configuration.AutoDetectChangesEnabled = true; 
} 

あなたがAddRangeを使用している場合は、here

AddRange()メソッドについてDetectChanges利用できる詳細情報についてはdb.Configuration.AutoDetectChangesEnabled = false

を省略することができ

db.ProductStatistics.AddRange(products); 

あなたのために何AddRangeを行います(デフォルト)、その後、DetectChangesは、任意のエンティティを追加する前に一度呼び出されますAutoDetectChangesEnabled is set to true場合

され、再び呼び出されることはありません。

これは、いくつかの状況では、AddRangeが呼び出しを呼び出すよりも大幅に実行する可能性があることを意味します。

既に他の状態でコンテキストに存在するエンティティは、状態が[追加済み]に設定されていることに注意してください。 AddRangeは、既にAdded状態のコンテキストにあるエンティティのためのno-opです。

関連する問題