Wie aktualisiere ich mehrere Zeilen gleichzeitig mit Linq zu SQL?

91

Tabelle:

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

Wenn der Benutzer userid = 1 sendet, ist friendids = 2,4,5 status = true

Bitte sagen Sie mir, dass die Frage, wie der Status der oben genannten Freundinnen aktualisiert werden soll, wahr ist. [2,3,4 auf einmal].

Vielen Dank

user1237131
quelle

Antworten:

233

Um eine Spalte zu aktualisieren, gibt es hier einige Syntaxoptionen:

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

Option 2

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

     db.SubmitChanges();
}

Option 3

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

Aktualisieren

Wie im Kommentar gefordert, kann es sinnvoll sein, zu zeigen, wie mehrere Spalten aktualisiert werden. Nehmen wir zum Zweck dieser Übung an, dass wir nicht nur die statusat-Werte aktualisieren möchten . Wir wollen aktualisieren nameund statuswo das friendidpasst. Hier sind einige Syntaxoptionen dafür:

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

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

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

Update 2

In der Antwort habe ich LINQ to SQL verwendet und in diesem Fall für die Festschreibung in die Datenbank lautet die Verwendung:

db.SubmitChanges();

Damit Entity Framework die Änderungen festschreiben kann, gilt Folgendes:

db.SaveChanges()
Arion
quelle
6
Und für mehrere Kommentare müssen Sie tun:records.ForEach(x=> { x.Deleted = true; x.DeletedByUserID = deletedByUserId; x.DeletedOn = DateTime.Now; });
JonH
2
Sollte es nicht sein db.SaveChanges()und nicht db.SubmitChanges()?
Bradlis7
3
... Alle drei Optionen sind gleich. Tatsächlich besteht der einzige Unterschied zwischen den ersten beiden darin, dass man eine Variable verwendet und man nicht. Beides zu haben ist nur ein erhöhter Lärm.
BlueRaja - Danny Pflughoeft
3
kann man darauf verzichten ToList()? Es ist ein Killer
Toolkit
2
Ruft ToList () je nach Bedingung alle Datensätze aus der Datenbank ab, nicht wahr? Wenn das stimmt, wäre es eine wirklich schlechte Leistung. Was ist, wenn es Millionen von Datensätzen gibt, laden wir sie in den Speicher, um diese Funktion zu betreiben? Bitte korrigieren Sie mich, wenn ich mich irre.
Jacob
20

Sie nicht die Verwendung ToList()Methode wie in der akzeptierten Antwort!

Beim Ausführen des SQL-Profilers habe ich überprüft und festgestellt, dass die ToList()Funktion alle Datensätze aus der Datenbank abruft. Es ist wirklich eine schlechte Leistung !!

Ich hätte diese Abfrage mit dem reinen SQL-Befehl wie folgt ausgeführt:

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

Dies würde das Update in einem Schuss ausführen, ohne auch nur eine Zeile auszuwählen.

Jacob
quelle
3

Das habe ich getan:

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

Hoffnung hilft jemandem.

Shaijut
quelle
Klappt wunderbar!
Yu Yang Jian
4
das ist schlecht, Sie Datenbank jedes Mal aufrufen , den Datensatz zu holen , featureund Sie sollten auch nicht hinzufügen context.SaveChanges()innen nach foreachdraußen foreach Schleife sein sollte.
Jawand Singh
1
Das SQL ist nicht dasselbe wie der EF-Code. In SQL ist es nur ein Befehl, der in allen Zeilen ausgeführt und die Tabelle aktualisiert wird. Der EF-Code nimmt alle Zeilen zuerst und aktualisiert die geänderten in der Datenbank. Wenn Sie also 1000 aktualisierte Zeilen haben, werden 1000 SQL-Aktualisierungen ausgeführt
Ashkan Sirous
1
@stom Es ist immer noch nicht dasselbe :) context.SaveChanges (); reicht einfach dein Update ein. Es wird immer noch 1000 Aktualisierungsbefehle geben, die jeweils die ID und nicht die SortOrder-Bedingung verwenden
Ashkan Sirous
2
@stom ExecuteSqlCommand existiert zu diesem Zweck auf EF, aber ich stimme zu, dass es nicht schön ist :) Wie auch immer, mein Punkt war, dass Sie einen SQL-Befehl und einen anderen EF-C # -Code geschrieben haben und behaupten, dass sie gleich sind. :)
Ashkan Sirous