จะอัปเดตหลายแถวพร้อมกันโดยใช้ linq เป็น sql ได้อย่างไร


95

ตาราง:

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].?

ขอบคุณ

คำตอบ:


240

หากต้องการอัปเดตหนึ่งคอลัมน์นี่คือตัวเลือกไวยากรณ์บางส่วน:

ตัวเลือกที่ 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();
}

อัปเดต

ตามที่ร้องขอในความคิดเห็นคุณอาจต้องแสดงวิธีการอัปเดตหลายคอลัมน์ สมมติว่าสำหรับจุดประสงค์ของแบบฝึกหัดนี้ที่เราต้องการไม่เพียงแค่อัปเดตstatusตอนที่ เราต้องการอัปเดต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 กับ SQL และในกรณีนั้นเพื่อส่งไปยังฐานข้อมูลการใช้งานคือ:

db.SubmitChanges();

แต่สำหรับ Entity Framework ที่จะยอมรับการเปลี่ยนแปลงนั้นคือ:

db.SaveChanges()

6
และสำหรับความคิดเห็นที่หลากหลายคุณต้องทำ:records.ForEach(x=> { x.Deleted = true; x.DeletedByUserID = deletedByUserId; x.DeletedOn = DateTime.Now; });
จอนห์

2
ไม่ควรdb.SaveChanges()และไม่ใช่db.SubmitChanges()หรือ?
bradlis7

3
... ทั้งสามตัวเลือกของคุณเหมือนกัน ในความเป็นจริงความแตกต่างเพียงอย่างเดียวระหว่างสองตัวแรกคือตัวแปรหนึ่งใช้ตัวแปรหนึ่งตัวไม่ได้ การมีทั้งสองอย่างเป็นเพียงเสียงที่เพิ่มขึ้น
BlueRaja - Danny Pflughoeft

3
เป็นไปได้ไหมที่จะทำโดยไม่ต้องToList()? มันเป็นนักฆ่า
Toolkit

2
ToList () รับระเบียนทั้งหมดจากฐานข้อมูลตามเงื่อนไขใช่หรือไม่ ถ้าถูกต้องมันจะมีประสิทธิภาพที่แย่มากถ้ามีหลายล้านเรกคอร์ดเราจะโหลดลงในหน่วยความจำเพื่อใช้งานฟังก์ชันนี้ โปรดแก้ไขฉันหากฉันเข้าใจผิด
เจคอบ

21

อย่าใช้ToList()วิธีการเช่นเดียวกับคำตอบที่ยอมรับ!

เรียกใช้ SQL profiler ฉันตรวจสอบและพบว่าToList()ฟังก์ชันได้รับบันทึกทั้งหมดจากฐานข้อมูล เป็นการแสดงที่แย่จริงๆ !!

ฉันจะเรียกใช้แบบสอบถามนี้ด้วยคำสั่ง pure 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 นำทุกแถวก่อนอัปเดตรายการที่เปลี่ยนแปลงบน DB ซึ่งหมายความว่าหากคุณมีแถวที่อัปเดต 1,000 แถวจะดำเนินการอัปเดต 1,000 sql
Ashkan Sirous

1
@stom มันยังไม่เหมือนเดิม :) context.SaveChanges (); เพียงแค่ส่งการอัปเดตของคุณ จะยังคงมีคำสั่งอัพเดต 1,000 คำสั่งแต่ละคำสั่งโดยใช้ id และไม่ใช่เงื่อนไข SortOrder
Ashkan Sirous

2
@stom ExecuteSqlCommand มีอยู่ใน EF เพื่อจุดประสงค์นี้ แต่ฉันยอมรับว่ามันไม่สวย :) อย่างไรก็ตามประเด็นของฉันคือคุณเขียนคำสั่ง SQL และรหัส EF-C # ที่แตกต่างกันและอ้างว่ามีค่าเท่ากัน :)
Ashkan Sirous
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.