2016-09-17 12 views
1

更新が必要なGUID(100,000以上)のローカルリストがあります。linqを使用してSQLに特定の列を更新

今私は、簡単な使用しています:

foreach(var id in GUIDs) 
{ 
    var objToUpdate = dataContext.table.Single(o=>o.id==id); 

    objToUpdate.val1=... 
    objToUpdate.val2=... 
    ... 


} 
dataContext.SubmitChanges(); 

このソリューションは非常に遅いです。 Singleメソッドを呼び出すたびに、レコード全体がDBから取得されます(プライマリキー以外のすべてのデータを上書きするため、レコードの必要はありません)。

本当に必要な2つの列しか取得できない方法はありますか? (主キーと他の1つの列)?

私はこのような何か行うと:

dataContext.table.Select(o => 

       new sqlRecord 
       { 
        PrimaryKey = o.PrimaryKey, 
        AnotherCol = o.AnotherCol 
       } 
      ); 

を私はエラーを取得:

Explicit construction of entity type '{0}' in query is not allowed. 

は、ストアドプロシージャを使用することはオプションではありません。正しいデータ値の設定は、外部リソースに応じて非常に複雑です。

var query = dataContext.table.Where(o => GUIDs.Contains(o.id)); 
foreach(var objToUpdate in query) 
{ 
    objToUpdate.val1 =...; 
    objToUpdate.val2 = ...; 
} 
dataContext.SubmitChanges(); 

私はGUIDのトンを持っていながら、これは、私が2100を超えるパラメータを使用していること、エラーが発生します。

(from ids in dataContext.fn_getGuidsFromString(String.Join("", GUIDs)) join o in dataContext.table on ids.id equals o.PrimaryKey select o) 

fn_getGuidsFromStringは、表関数は、SQLにあります。このため

、私は代替手段を使用しています。これはwhereとContainsを使う方が良いでしょう。

私の問題は、この動作が遅すぎるということです。この表には200以上の列があり、そのうちのいくつかは多くのデータを持つテキストであることを知っていなければなりません。

dataContext.table.Single(o=>o.id==id).select(o=>new {o.id, o.anotherCol}); 

が、これで私はレコードを更新することはできません。

dataContext.table.Single(o=>o.id==id); 

は(データに応じて)この後、約20倍遅くなります。

ご意見はありますか? よろしく

+0

一括アップデートを使用しようとすると、あなたの場合ストア手順を使用する必要があります。 http://stackoverflow.com/questions/17274430/efficient-way-to-do-bulk-insert-update-withentent-framework – Chandru

+0

私はあなたのコードのどのラインが時間のかかるものかを判断するためにストップウォッチを使用することを推奨します。そこから改善の方向に進むことができます。 – Niklas

+0

ここをクリックしてください:http://stackoverflow.com/questions/8223942/linq2sql-select-only-some-column-but-stillable-to-submit-changes – astidham2003

答えて

0

特定の列から値を取得するには、このクエリを使用します。

var objToUpdate = (from o in dataContext.Table 
        where o.id == guid 
        select new {o.Column1, o.Column2, ...}).Single(); 

それは文脈の追跡の一部ではない匿名型内に突出するのでselect new {...}構文は、重要です。取得したオブジェクトがコンテキストトラッキングの一部であった場合、同じ主キーを持つ2つのオブジェクトを追跡できず、Attachが主キーを持つオブジェクトトラックを追加するため、Attachメソッドを次に使用するとエラーが発生します。 。今

、データベースだけで更新された値を持つエンティティのスタブを作成し、正しいプライマリキー使用して更新する:すべての変更が行われた後

TableName stub = new TableName(); 
// One of these should be a primary key. 
stub.val1 = ...; 
stub.val2 = ...; 
TableName.Attach(stub); // Will throw an exception if the row with this primary key is already being tracked in memory. 

を、

dataContext.SubmitChanges(); 
を呼び出します

重要なのは、古い値が不要で、主キーがすべて既知である場合、古い行を取り込むためのクエリをスキップできることです。スタブは、まずデータベースに問い合わせることなく追加することができます。その後、SubmitChangesが呼び出されると、正しい行が更新されます。

+0

ありがとう、それは問題を解決します。私の場合は別の問題がありました。私はこのステートメントを使用してデータを取得していました: (dataContext.fn_getGuidsFromString(String.Join( ""、GUIDs))のidsからids.idと等しいo.PrimaryKeyを選択o) dataContext、取得された項目はすでに添付されていました。 私はエラーが発生しました。「既に使用されているキーを持つエンティティを追加できません。 私は匿名のオブジェクトに変更したとき、それを解決します。ありがとうございました! – mateuszwdowiak

+0

私はちょうど今、私はAttachingの例外がないことを発見しました。私は例外が発生します:行が見つからない、または変更されました。変更を送信しようとしています。これは解決されていません。 – mateuszwdowiak

+0

@mateuszwdowiak Attachは、その主キーを持つレコードがデータベースに存在すると仮定します。 SubmitChangesの呼び出しの前にレコードが存在し、削除されていませんか? foreachループの中でSubmitChanges()を動かし、いくつかの繰り返しを実行して、このエラーがすべての行でスローされたかどうかを確認することができます。内部例外に追加情報はありますか?失敗した操作を示すSQLログにアクセスできますか? – astidham2003

関連する問題