come aggiornare più righe contemporaneamente utilizzando linq a sql?


91

Tavolo:

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

se l'utente invia userid = 1, friendids = 2,4,5 status = true

per favore dimmi che la domanda su come aggiornare lo stato di tutti gli amici è vera. [2,3,4 alla volta].?

Grazie

Risposte:


234

Per aggiornare una colonna, ecco alcune opzioni di sintassi:

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

opzione 2

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

     db.SubmitChanges();
}

Opzione 3

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

Aggiornare

Come richiesto nel commento, potrebbe avere senso mostrare come aggiornare più colonne. Quindi diciamo ai fini di questo esercizio che non vogliamo solo aggiornare gli statusat. Vogliamo aggiornare namee statusdove friendidcorrisponde. Ecco alcune opzioni di sintassi per questo:

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

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

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

Aggiorna 2

Nella risposta stavo usando LINQ to SQL e in quel caso per eseguire il commit sul database l'utilizzo è:

db.SubmitChanges();

Ma affinché Entity Framework effettui il commit delle modifiche è:

db.SaveChanges()

6
E per più commenti devi fare:records.ForEach(x=> { x.Deleted = true; x.DeletedByUserID = deletedByUserId; x.DeletedOn = DateTime.Now; });
JonH

2
Non dovrebbe essere db.SaveChanges()e no db.SubmitChanges()?
bradlis7

3
... Tutte e tre le tue opzioni sono le stesse. In effetti l'unica differenza tra i primi due è che uno usa una variabile e l'altro no. Avere entrambi è solo un aumento del rumore.
BlueRaja - Danny Pflughoeft

3
è possibile farne a meno ToList()? È un killer
Toolkit

2
ToList () ottiene tutti i record dal database, in base alle condizioni, non è vero? Se è così, sarebbe davvero una pessima prestazione, e se ci fossero milioni di record, li cariciamo nella memoria per azionare questa funzione? Per favore correggimi se sbaglio.
Jacob il

20

Non utilizzare il ToList()metodo come nella risposta accettata!

Eseguendo SQL Profiler, ho verificato e scoperto che la ToList()funzione ottiene tutti i record dal database. È davvero una pessima prestazione !!

Avrei eseguito questa query con il comando sql puro come segue:

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

Ciò azionerebbe l'aggiornamento in un colpo solo senza selezionare nemmeno una riga.


3

Questo è quello che ho fatto:

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

La speranza aiuta qualcuno.


Funziona come un fascino!
yu yang Jian

4
questo è un male, stai chiamando il database ogni volta per recuperare il record featuree inoltre non dovresti aggiungere context.SaveChanges()al foreachsuo interno dovrebbe essere al di fuori del ciclo foreach.
Jawand Singh

1
L'SQL non è lo stesso del codice EF. In SQL è solo 1 comando che viene eseguito su tutte le righe e aggiorna la tabella. Il codice EF prende prima tutte le righe, aggiorna quelle modificate sul DB, il che significa che se hai 1000 righe aggiornate, eseguirà 1000 aggiornamenti sql
Ashkan Sirous

1
@stom Non è ancora lo stesso :) context.SaveChanges (); invia solo il tuo aggiornamento. ci saranno ancora 1000 comandi di aggiornamento ciascuno utilizzando l'id e non la condizione SortOrder
Ashkan Sirous

2
@stom ExecuteSqlCommand esiste su EF per questo scopo, ma su sono d'accordo che non è carino :) Comunque, il mio punto era che hai scritto un comando SQL e un codice EF-C # diverso e hai affermato che sono uguali. :)
Ashkan Sirous
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.