2011-06-16 1 views
2

複数のレコードをテーブルに挿入しようとしていますが、各レコードに以前のシーケンス番号挿入されたレコード。例えば各インサートでシーケンス検索関数を呼び出す際に、LINQ to SQLで一度に複数のレコードを挿入する方法

var db = new StoreDataContext(); 
var inserts = payments.Select(p => new payment 
{ 
    order_fk = p.order_fk, line_no = DbMethods.GetNextLine(p.order_fk), 
    amount = p.amount 
}); 

db.payments.InsertAllOnSubmit(inserts); 
db.SubmitChanges(ConflictMode.FailOnFirstConflict); 

DbMethods.GetNextLineは行くと、その特定の順序のためのMAX(line_no) + 1を取得するSQLスカラー関数です。

私の問題は、実際の挿入が行われる前に関数が実行されるため、line_noの値はすべて同じです。とにかく、各レコードを別々に提出しなければならないのですか?

+0

なぜ、line_noをアイデンティティにしないのですか? – cadrell0

+0

残念ながら私はテーブルを変更することはできません。 – ddechant

+0

それは開発の非常に大きな障害です。データアクセス層を作成している人はスキーマを変更できません。誰か他の人に修正を提案してもらえますか、それとも完全にこれに固執していますか? – StriplingWarrior

答えて

2

を試しLINQ to SQLはこのような何かを行うには、私が知っている唯一の方法は、トランザクションでそれをラップすることです。

var db = new StoreDataContext(); 
using(var scope = new TransactionScope()){   
    foreach(var p in payments){ 
     db.payments.Insert(new payment 
          { order_fk = p.order_fk, 
           line_no = DbMethods.GetNextLine(p.order_fk),  
           amount = p.amount 
          }); 
     db.SubmitChanges(ConflictMode.FailOnFirstConflict); 
    } 
    scope.Complete(); 
} 
+1

決して 'SubmitChanges'を何度も呼び出さないでください - 私は' scope.Complete() 'の直前にループの外で一度呼び出すといいでしょう –

1

これを回避する最も簡単な方法は、データベースを活用することです。たとえば、支払いが挿入されるたびに行番号を設定するトリガーを作成できます。この方法では、このテーブルに支払いを入力する他の手段を使用しても、データは一貫しています。

ただし、スキーマの変更が許可されていない場合は、挿入しようとしている支払いをorder_fkでグループ化してから、挿入を試みる前に適切にインクリメントしてください。アトミック性を保証するためにトランザクションスコープを使用できるはずですが、これを非常に頻繁にやっているとかなり遅くなります。

2

この

var db = new StoreDataContext(); 
Int32 lineNo = DbMethods.GetNextLine(p.order_fk); 
var inserts = payments.Select(p => new payment 
{ 
    order_fk = p.order_fk, 
    amount = p.amount 
}); 
foreach(var item on inserts) 
{ 
    item.line_no = LineNo; 
    LineNo++; 
} 
db.payments.InsertAllOnSubmit(inserts); 
db.SubmitChanges(ConflictMode.FailOnFirstConflict); 
関連する問題