как обновить несколько строк за раз с помощью linq to sql?

94

Таблица:

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 за раз].?

Благодарность

user1237131
источник

Ответы:

238

Вот несколько вариантов синтаксиса для обновления одного столбца:

Опция 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();
}

Вариант 2

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

     db.SubmitChanges();
}

Вариант 3

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

Обновить

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

Опция 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();
}

Вариант 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();
}

Вариант 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();
}

Обновление 2

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

db.SubmitChanges();

Но для Entity Framework для фиксации изменений это:

db.SaveChanges()
Арион
источник
6
И для нескольких комментариев вам нужно сделать:records.ForEach(x=> { x.Deleted = true; x.DeletedByUserID = deletedByUserId; x.DeletedOn = DateTime.Now; });
JonH
2
Не должно быть db.SaveChanges()и нет db.SubmitChanges()?
bradlis7 02
3
... Все три варианта одинаковы. Фактически, единственная разница между первыми двумя состоит в том, что один использует переменную, а другой - нет. И то, и другое - это просто повышенный шум.
BlueRaja - Дэнни Пфлугофт
3
можно ли обойтись без ToList()? Это убийца
Toolkit
2
Получает ли ToList () все записи из базы данных в соответствии с условием, не так ли? Если это верно, это будет действительно плохая производительность. Что, если есть миллионы записей, мы загружаем их в память для работы этой функции? Пожалуйста, поправьте меня, если я ошибаюсь.
Джейкоб
20

Не используйте ToList()метод, указанный в принятом ответе!

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

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

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

Это позволит выполнить обновление за один раз, не выбирая ни одной строки.

Джейкоб
источник
3

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

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

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

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