¿Cómo actualizar las múltiples filas a la vez usando linq to sql?

91

Mesa:

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 el usuario envía userid = 1, friendids = 2,4,5 status = true

por favor dígame que la consulta sobre cómo actualizar el estado anterior de todos los amigos es verdadera. [2,3,4 a la vez].?

Gracias

usuario1237131
fuente

Respuestas:

234

Para actualizar una columna, aquí hay algunas opciones de sintaxis:

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

opcion 2

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

     db.SubmitChanges();
}

Opción 3

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

Actualizar

Como se solicita en el comentario, podría tener sentido mostrar cómo actualizar varias columnas. Entonces, digamos, a los efectos de este ejercicio, que no solo queremos actualizar las statusen. Queremos actualizar namey statusdónde friendidcoincide. Aquí hay algunas opciones de sintaxis para eso:

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

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

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

Actualización 2

En la respuesta, estaba usando LINQ to SQL y, en ese caso, para comprometerme con la base de datos, el uso es:

db.SubmitChanges();

Pero para que Entity Framework confirme los cambios es:

db.SaveChanges()
Arion
fuente
6
Y para varios comentarios que debe hacer:records.ForEach(x=> { x.Deleted = true; x.DeletedByUserID = deletedByUserId; x.DeletedOn = DateTime.Now; });
JonH
2
¿No debería ser db.SaveChanges()y no db.SubmitChanges()?
bradlis7
3
... Las tres opciones son las mismas. De hecho, la única diferencia entre los dos primeros es que uno usa una variable y el otro no. Tener ambos es solo un aumento de ruido.
BlueRaja - Danny Pflughoeft
3
¿Es posible prescindir ToList()? Es un asesino
Kit de herramientas
2
¿ToList () obtiene todos los registros de la base de datos, de acuerdo con la condición, no es así? Si eso es correcto, sería un rendimiento realmente malo. ¿Qué pasa si hay millones de registros, los cargamos en la memoria para operar esta función? Por favor corríjame si me equivoco.
Jacob
20

¡No use el ToList()método como en la respuesta aceptada!

Al ejecutar SQL Profiler, verifiqué y encontré que la ToList()función obtiene todos los registros de la base de datos. ¡Es una actuación realmente mala!

Habría ejecutado esta consulta mediante el comando sql puro de la siguiente manera:

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

Esto operaría la actualización de una sola vez sin seleccionar ni una fila.

Jacob
fuente
3

Esto es lo que hice:

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 esperanza ayuda a alguien.

shaijut
fuente
¡Funciona de maravilla!
Yu yang Jian
4
esto es malo, está llamando a la base de datos cada vez para obtener el registro featurey tampoco debe agregarlo context.SaveChanges()dentro foreach, debe estar fuera de cada bucle.
Jawand Singh
1
El SQL no es el mismo que el código EF. En SQL, es solo un comando que se ejecuta en todas las filas y actualiza la tabla. El código EF toma todas las filas primero, actualiza las cambiadas en la base de datos, lo que significa que si tiene 1000 filas actualizadas, ejecutará 1000 actualizaciones de sql
Ashkan Sirous
1
@stom Todavía no es lo mismo :) context.SaveChanges (); solo envía su actualización. todavía habrá 1000 comandos de actualización, cada uno con la identificación y no la condición SortOrder
Ashkan Sirous
2
@stom ExecuteSqlCommand existe en EF para este propósito, pero estoy de acuerdo en que no es bonito :) De todos modos, mi punto fue que ha escrito un comando SQL y un código EF-C # diferente y afirmando que son iguales. :)
Ashkan Sirous