como atualizar as várias linhas de uma vez usando linq para sql?

91

Tabela:

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 o usuário enviar userid = 1, friendids = 2,4,5 status = true

por favor, diga-me que a pergunta sobre como atualizar o status de friendids acima de tudo é verdadeira. [2,3,4 por vez].?

obrigado

user1237131
fonte

Respostas:

233

Para atualizar uma coluna, aqui estão algumas opções de sintaxe:

Opção 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();
}

opção 2

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

     db.SubmitChanges();
}

Opção 3

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

Atualizar

Conforme solicitado no comentário, pode fazer sentido mostrar como atualizar várias colunas. Portanto, digamos, para o propósito deste exercício, que não desejamos apenas atualizar as statusunidades. Queremos atualizar namee statusonde o friendidestá combinando. Aqui estão algumas opções de sintaxe para isso:

Opção 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();
}

opção 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();
}

Opção 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();
}

Atualização 2

Na resposta, eu estava usando LINQ to SQL e, nesse caso, para comprometer o banco de dados, o uso é:

db.SubmitChanges();

Mas para o Entity Framework comprometer as mudanças, é:

db.SaveChanges()
Arion
fonte
6
E para vários comentários, você precisa fazer:records.ForEach(x=> { x.Deleted = true; x.DeletedByUserID = deletedByUserId; x.DeletedOn = DateTime.Now; });
JonH
2
Não deveria ser db.SaveChanges()e não db.SubmitChanges()?
bradlis7
3
... Todas as três opções são as mesmas. Na verdade, a única diferença entre os dois primeiros é que um usa uma variável e o outro não. Ter ambos é apenas aumentar o ruído.
BlueRaja - Danny Pflughoeft
3
é possível fazer sem ToList()? É um assassino
Toolkit
2
ToList () obtém todos os registros do banco de dados, de acordo com a condição, não é? Se isso estiver certo, seria um desempenho muito ruim. E se houver milhões de registros, nós os carregarmos na memória para operar esta função? Por favor, me corrija se eu estiver enganado.
Jacob,
20

Não use o ToList()método como na resposta aceita!

Executando o SQL Profiler, verifiquei e descobri que a ToList()função obtém todos os registros do banco de dados. É um desempenho muito ruim !!

Eu teria executado essa consulta pelo comando sql puro da seguinte maneira:

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

Isso operaria a atualização de uma vez, sem selecionar nem mesmo uma linha.

Jacob
fonte
3

Isso é o que eu fiz:

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

A esperança ajuda alguém.

shaijut
fonte
Funciona como um encanto!
yu yang Jian
4
isso é ruim, você está chamando o banco de dados toda vez para buscar o registro featuree também não deve adicionar context.SaveChanges()dentro foreachdele, deve estar fora do loop foreach.
Jawand Singh
1
O SQL não é o mesmo que o código EF. No SQL, é apenas um comando que é executado em todas as linhas e atualiza a tabela. O código EF pega todas as linhas primeiro, atualiza as alteradas no banco de dados, o que significa que se você tiver 1000 linhas atualizadas, ele executará 1000 atualizações sql
Ashkan Sirous
1
@stom Não é mais o mesmo :) context.SaveChanges (); apenas envia sua atualização. ainda haverá 1000 comandos de atualização, cada um usando o id e não a condição SortOrder
Ashkan Sirous
2
@stom ExecuteSqlCommand existe no EF para este propósito, mas eu concordo que não é bonito :) De qualquer forma, meu ponto é que você escreveu um comando SQL e um código EF-C # diferente e alegando que eles são iguais. :)
Ashkan Sirous