comment mettre à jour les plusieurs lignes à la fois en utilisant linq en sql?

91

Table:

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

si l'utilisateur envoie userid = 1, friendids = 2,4,5 status = true

s'il vous plaît dites-moi que la question pour savoir comment mettre à jour le statut de tous les amis ci-dessus est vraie. [2,3,4 à la fois].?

Merci

user1237131
la source

Réponses:

234

Pour mettre à jour une colonne, voici quelques options de syntaxe:

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

Mettre à jour

Comme demandé dans le commentaire, il peut être judicieux de montrer comment mettre à jour plusieurs colonnes. Donc, disons aux fins de cet exercice que nous ne voulons pas seulement mettre à jour les statusat. Nous voulons mettre à jour nameet statusoù le friendidcorrespond. Voici quelques options de syntaxe pour cela:

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

Mise à jour 2

Dans la réponse, j'utilisais LINQ to SQL et dans ce cas, pour m'engager dans la base de données, l'utilisation est:

db.SubmitChanges();

Mais pour Entity Framework pour valider les modifications, c'est:

db.SaveChanges()
Arion
la source
6
Et pour plusieurs commentaires, vous devez faire:records.ForEach(x=> { x.Deleted = true; x.DeletedByUserID = deletedByUserId; x.DeletedOn = DateTime.Now; });
JonH
2
Ne devrait-il pas être db.SaveChanges()et non db.SubmitChanges()?
bradlis7
3
... Vos trois options sont identiques. En fait, la seule différence entre les deux premiers est que l'on utilise une variable et l'autre pas. Avoir les deux n'est qu'un bruit accru.
BlueRaja - Danny Pflughoeft
3
est-il possible de s'en passer ToList()? C'est un tueur
Boîte à outils
2
ToList () obtient-il tous les enregistrements de la base de données, selon la condition, n'est-ce pas? Si c'est vrai, ce serait vraiment de mauvaises performances, et s'il y a des millions d'enregistrements, on les charge dans la mémoire pour faire fonctionner cette fonction? Veuillez me corriger si je me trompe.
Jacob
20

N'utilisez pas la ToList()méthode comme dans la réponse acceptée!

En exécutant le profileur SQL, j'ai vérifié et trouvé que la ToList()fonction récupère tous les enregistrements de la base de données. C'est vraiment une mauvaise performance !!

J'aurais exécuté cette requête par pure commande sql comme suit:

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

Cela opérerait la mise à jour en un seul coup sans sélectionner ne serait-ce qu'une seule ligne.

Jacob
la source
3

C'est ce que j'ai fait:

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

L'espoir aide quelqu'un.

shaijut
la source
Fonctionne comme un charme!
yu yang Jian
4
c'est mauvais, vous appelez la base de données à chaque fois pour récupérer l'enregistrement featureet vous ne devriez pas non plus ajouter à l' context.SaveChanges()intérieur, foreachil devrait être à l'extérieur de la boucle foreach.
Jawand Singh
1
Le SQL n'est pas le même que le code EF. En SQL, il n'y a qu'une seule commande qui s'exécute sur toutes les lignes et met à jour la table. Le code EF prend toutes les lignes en premier, met à jour celles modifiées sur DB, ce qui signifie que si vous avez 1000 lignes mises à jour, il exécutera 1000 mises à jour sql
Ashkan Sirous
1
@stom Ce n'est pas toujours le même :) context.SaveChanges (); soumet simplement votre mise à jour. il y aura toujours 1000 commandes de mise à jour utilisant chacune l'id et non la condition SortOrder
Ashkan Sirous
2
@stom ExecuteSqlCommand existe sur EF à cette fin, mais je suis d'accord que ce n'est pas joli :) Quoi qu'il en soit, mon point était que vous avez écrit une commande SQL et un code EF-C # différent et affirmant qu'ils sont égaux. :)
Ashkan Sirous