jak zaktualizować wiele wierszy naraz za pomocą linq do sql?

93

Stół:

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

jeśli użytkownik wyśle ​​userid = 1, friendids = 2,4,5 status = true

proszę powiedz mi, że pytanie, jak zaktualizować powyższy status wszystkich znajomych jest prawdziwe. [2,3,4 naraz].?

dzięki

user1237131
źródło

Odpowiedzi:

237

Aby zaktualizować jedną kolumnę, oto kilka opcji składni:

opcja 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();
}

Opcja 2

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

     db.SubmitChanges();
}

Wariant 3

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

Aktualizacja

Zgodnie z prośbą zawartą w komentarzu warto pokazać, jak zaktualizować wiele kolumn. Powiedzmy więc na potrzeby tego ćwiczenia, że ​​nie chcemy tylko aktualizować statusat one. Chcemy zaktualizować namei statusgdzie friendidpasuje. Oto kilka opcji składni:

opcja 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();
}

Opcja 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();
}

Wariant 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();
}

Zaktualizuj 2

W odpowiedzi użyłem LINQ to SQL iw tym przypadku do zatwierdzenia do bazy danych użyto:

db.SubmitChanges();

Ale aby Entity Framework zatwierdził zmiany, jest to:

db.SaveChanges()
Arion
źródło
6
W przypadku wielu komentarzy musisz zrobić:records.ForEach(x=> { x.Deleted = true; x.DeletedByUserID = deletedByUserId; x.DeletedOn = DateTime.Now; });
JonH
2
Nie powinno db.SaveChanges()i nie powinno db.SubmitChanges()?
bradlis7
3
... Wszystkie trzy opcje są takie same. W rzeczywistości jedyna różnica między pierwszymi dwoma polega na tym, że używa się zmiennej, a nie. Posiadanie obu to po prostu zwiększony hałas.
BlueRaja - Danny Pflughoeft
3
czy można się bez niego obejść ToList()? To zabójca
zestaw narzędzi
2
Czy ToList () pobiera wszystkie rekordy z bazy danych, zgodnie z warunkiem, prawda? Jeśli to prawda, to byłaby naprawdę kiepska wydajność. A jeśli są miliony rekordów, załadujemy je do pamięci, aby obsługiwać tę funkcję? Proszę, popraw mnie, jeśli się mylę.
Jacob
20

Nie używaj ToList()metody jak w zaakceptowanej odpowiedzi!

Uruchamiając profiler SQL, zweryfikowałem i stwierdziłem, że ToList()funkcja pobiera wszystkie rekordy z bazy danych. To naprawdę kiepski występ !!

Uruchomiłbym to zapytanie za pomocą czystego polecenia sql w następujący sposób:

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

Spowoduje to uruchomienie aktualizacji w jednym ujęciu bez wybierania nawet jednego wiersza.

Jakub
źródło
3

Oto co zrobiłem:

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();
}

Nadzieja pomaga komuś.

shaijut
źródło
Działa jak marzenie!
yu yang Jian
4
to jest złe, za każdym razem dzwonisz do bazy danych, aby pobrać rekord, featurea także nie powinieneś dodawać, że w context.SaveChanges()środku foreachpowinna znajdować się poza pętlą foreach.
Jawand Singh
1
Kod SQL to nie to samo, co kod EF. W SQL to tylko 1 polecenie, które działa na wszystkich wierszach i aktualizuje tabelę. Kod EF pobiera najpierw wszystkie wiersze, aktualizuje zmienione wiersze w bazie danych, co oznacza, że ​​jeśli masz 1000 zaktualizowanych wierszy, wykona aktualizacje 1000 sql
Ashkan Sirous
1
@stom To już nie to samo :) context.SaveChanges (); po prostu przesyła Twoją aktualizację. nadal będzie 1000 poleceń aktualizacji, z których każde będzie używać identyfikatora, a nie warunku SortOrder
Ashkan Sirous
2
@stom ExecuteSqlCommand istnieje w tym celu na EF, ale zgadzam się, że nie jest ładny :) W każdym razie chodziło mi o to, że napisałeś polecenie SQL i inny kod EF-C # i twierdziłem, że są równe. :)
Ashkan Sirous