linq to sqlを使用して一度に複数の行を更新する方法は?


91

テーブル:

id     userid  friendid   name    status
1      1        2         venkat  false
2      1        3         sai     true
3      1        4         arun    false
4      1        5         arjun   false

ユーザーがuserid = 1、friendids = 2,4,5 status = trueを送信した場合

上記のすべてのフレンドIDステータスを更新する方法についてのクエリを教えてください。[一度に2、3、4]。

ありがとう

回答:


234

ここで1つの列を更新するには、いくつかの構文オプションがあります。

オプション1

var ls=new int[]{2,3,4};
using (var db=new SomeDatabaseContext())
{
    var some= db.SomeTable.Where(x=>ls.Contains(x.friendid)).ToList();
    some.ForEach(a=>a.status=true);
    db.SubmitChanges();
}

オプション2

using (var db=new SomeDatabaseContext())
{
     db.SomeTable
       .Where(x=>ls.Contains(x.friendid))
       .ToList()
       .ForEach(a=>a.status=true);

     db.SubmitChanges();
}

オプション3

using (var db=new SomeDatabaseContext())
{
    foreach (var some in db.SomeTable.Where(x=>ls.Contains(x.friendid)).ToList())
    {
        some.status=true;
    }
    db.SubmitChanges();
}

更新

コメントで要求されているように、複数の列を更新する方法を示すことは意味があるかもしれません。したがって、この演習の目的で、単にstatusat を更新するだけではない、としましょう。私たちは、更新したいnamestatusどこfriendidマッチングがあります。そのための構文オプションは次のとおりです。

オプション1

var ls=new int[]{2,3,4};
var name="Foo";
using (var db=new SomeDatabaseContext())
{
    var some= db.SomeTable.Where(x=>ls.Contains(x.friendid)).ToList();
    some.ForEach(a=>
                    {
                        a.status=true;
                        a.name=name;
                    }
                );
    db.SubmitChanges();
}

オプション2

using (var db=new SomeDatabaseContext())
{
    db.SomeTable
        .Where(x=>ls.Contains(x.friendid))
        .ToList()
        .ForEach(a=>
                    {
                        a.status=true;
                        a.name=name;
                    }
                );
    db.SubmitChanges();
}

オプション3

using (var db=new SomeDatabaseContext())
{
    foreach (var some in db.SomeTable.Where(x=>ls.Contains(x.friendid)).ToList())
    {
        some.status=true;
        some.name=name;
    }
    db.SubmitChanges();
}

アップデート2

答えでは、LINQ to SQLを使用しており、その場合、データベースにコミットするための使用法は次のとおりです。

db.SubmitChanges();

しかし、Entity Frameworkが変更をコミットするには、次のようになります。

db.SaveChanges()

6
そして、あなたがする必要がある複数のコメントのために:records.ForEach(x=> { x.Deleted = true; x.DeletedByUserID = deletedByUserId; x.DeletedOn = DateTime.Now; });
JonH

2
それはそうではdb.SaveChanges()ありませんdb.SubmitChanges()か?
bradlis7 14

3
... 3つのオプションはすべて同じです。実際、最初の2つの違いは、1つは変数を使用し、1つは使用しないことです。両方があるとノイズが増えるだけです。
BlueRaja-Danny Pflughoeft 2015

3
なしで行うことは可能ToList()ですか?それはキラーです
ツールキット

2
ToList()は、条件に従って、データベースからすべてのレコードを取得しますか?それが正しい場合、それは本当に悪いパフォーマンスになります、何百万ものレコードがある場合、この関数を操作するためにそれらをメモリにロードしますか?間違えたら訂正してください。
ジェイコブ

20

ToList()受け入れられた答えのようにメソッドを使用しないでください

SQLプロファイラーを実行して確認したところ、このToList()関数はデータベースからすべてのレコードを取得します。本当に悪い性能です!!

このクエリは、次のように純粋なSQLコマンドで実行します。

string query = "Update YourTable Set ... Where ...";    
context.Database.ExecuteSqlCommandAsync(query, new SqlParameter("@ColumnY", value1), new SqlParameter("@ColumnZ", value2));

これにより、1行も選択せずに、更新をワンショットで操作できます。


3

これは私がやったことです:

EF:

using (var context = new SomeDBContext())
{
    foreach (var item in model.ShopItems)  // ShopItems is a posted list with values 
    {    
        var feature = context.Shop
                             .Where(h => h.ShopID == 123 && h.Type == item.Type).ToList();

        feature.ForEach(a => a.SortOrder = item.SortOrder);
    }

    context.SaveChanges();
}

希望は誰かを助けます。


魅力的な作品!
ユーヤンジャン2017

4
これは悪いです、あなたがレコードをフェッチするたびにデータベースを呼び出しているfeatureし、また、あなたが追加してはならないcontext.SaveChanges()の内側にforeachそれが外foreachループでなければなりません。
Jawand Singh 2017

1
SQLはEFコードと同じではありません。SQLでは、すべての行で実行されてテーブルを更新するコマンドは1つだけです。EFコードは最初にすべての行を取得し、DBで変更された行を更新します。つまり、1000行の更新がある場合、1000のSQL更新を実行します
Ashkan Sirous

1
@stomまだ同じではありません:) context.SaveChanges(); 更新を送信するだけです。それでも、SortOrder条件ではなく、IDを使用する1000個の更新コマンドがあります
Ashkan Sirous

2
@stom ExecuteSqlCommandは、この目的のためにEFに存在しますが、私はそれがきれいではないことに同意します:)とにかく、私のポイントは、SQLコマンドと別のEF-C#コードを記述し、それらが等しいと主張したことです。:)
Ashkan Sirous
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.