як оновити кілька рядків за раз, використовуючи linq до sql?


91

Таблиця:

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

скажіть мені, будь ласка, запит щодо оновлення вищевказаного статусу friendids відповідає дійсності. [2,3,4 за раз].?

Дякую

Відповіді:


234

Щоб оновити один стовпець, ось кілька варіантів синтаксису:

Варіант 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. Ми хочемо оновити 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,

3
... Усі три ваші варіанти однакові. Насправді єдина різниця між першими двома полягає в тому, що один використовує змінну, а інший - ні. Наявність обох - це просто підвищений шум.
BlueRaja - Danny Pflughoeft

3
чи можна обійтися без ToList()? Це вбивця
Набір інструментів

2
Чи отримує ToList () всі записи з бази даних, відповідно до умови, чи не так? Якщо це правильно, це буде насправді погана продуктивність. Що робити, якщо є мільйони записів, ми завантажуємо їх в пам’ять для роботи цієї функції? Будь ласка, виправте мене, якщо я помиляюся.
Яків

20

Не використовуйтеToList() метод, як у прийнятій відповіді!

Запустивши SQL profiler, я перевірив і виявив це 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.
Jawand Singh

1
SQL не такий, як код EF. У SQL це лише 1 команда, яка працює у всіх рядках та оновлює таблицю. Код EF спочатку бере всі рядки, оновлює змінені в БД, це означає, що якщо у вас є 1000 оновлених рядків, він виконає оновлення 1000 sql
Ashkan Sirous

1
@stom Це ще не те саме :) context.SaveChanges (); просто подає ваше оновлення. все одно буде 1000 команд оновлення, кожна з яких використовує ідентифікатор, а не умову SortOrder
Ashkan Sirous

2
@stom ExecuteSqlCommand для цього існує в EF, але, погоджуюсь, це не дуже красиво :) У будь-якому випадку, мій сенс полягав у тому, що ви написали команду SQL та інший код EF-C # і стверджуєте, що вони рівні. :)
Ашкан Сіроус
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.