Вопрос по c#, linq, entity-framework, linq-to-sql – Как обновить несколько строк одновременно, используя LINQ для SQL?

78

Таблица:

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

если пользователь отправляет userid = 1, friendids = 2,4,5 status = true

пожалуйста, скажите мне, что запрос на обновление вышеуказанного статуса «дружественный» является истинным. [2,3,4 за один раз].

Спасибо

Ваш Ответ

3   ответа
15

Do not использоватьToList() метод как в принятом ответе!

Запустив SQL Profiler, я проверил и обнаружил, чтоToList() Функция получает все записи из базы данных. Это действительно плохое выступление!

Я бы запустил этот запрос чистой командой sql следующим образом:

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

Это будет работать обновление в один выстрел без выбора даже одной строки.

203

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

Update

В соответствии с просьбой в комментарии, возможно, имеет смысл показать, как обновить несколько столбцов. Так что для целей этого упражнения скажем, что мы хотим не просто обновитьstatus в единицах. Мы хотим обновитьname а такжеstatus гдеfriendid совпадает. Вот несколько вариантов синтаксиса для этого:

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

В ответе я использовал LINQ to SQL, и в этом случае для фиксации в базе данных используется:

db.SubmitChanges();

Но для Entity Framework, чтобы зафиксировать изменения это:

db.SaveChanges()
Не должно ли это бытьdb.SaveChanges() и неdb.SubmitChanges()?
можно ли обойтись безToList()? Это убийца
@ИнструментарийToList() просто форсирует перечисление токаIQueryable или жеIEnumerable, Выhave в конечном итоге перечислитьsomething делать любую работу вообще. Таким образом, если вы обнаружили, что это снижает производительность, вы делаете это не в тот момент - когда, например, это может привести к перечислению каждой строки в базе данных, поскольку вы не указали надлежащие условия. Честно говоря, это НЕ проблема. Но да, это будет генерировать отдельное обновление для каждой строки, поэтому оно не будет работать хорошо для десятков тысяч из них ...
И для нескольких комментариев вам нужно сделать:records.ForEach(x=> { x.Deleted = true; x.DeletedByUserID = deletedByUserId; x.DeletedOn = DateTime.Now; });
... Все три ваших варианта одинаковы. Фактически единственное различие между первыми двумя состоит в том, что один использует переменную, а другой - нет. И то, и другое только увеличило шум.
1

Вот что я сделал:

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

Надежда помогает кому-то.

это плохо, вы вызываете базу данных каждый раз, чтобы получить записьfeature а также не стоит добавлятьcontext.SaveChanges() внутриforeach это должно быть вне цикла foreach.
@AshkanSirous, спасибо, что сделали изменения.
@stom ExecuteSqlCommand существует в EF для этой цели, но я согласен, что это нехорошо :) В любом случае, я хотел сказать, что вы написали команду SQL и другой код EF-C # и утверждали, что они равны. :)
Работает как шарм!
SQL не совпадает с кодом EF. В SQL это всего лишь 1 команда, которая выполняется во всех строках и обновляет таблицу. Код EF сначала берет все строки, обновляет измененные в БД, а это означает, что если у вас есть 1000 обновленных строк, он выполнит 1000 sql обновлений

Похожие вопросы