ลบระเบียนเดียวจาก Entity Framework หรือไม่


195

ผมมีตาราง SQL Server ใน Entity Framework ชื่อมีคอลัมน์คีย์เดียวชื่อemployID

ฉันจะลบระเบียนเดียวจากตารางโดยใช้ Entity Framework ได้อย่างไร


2
db.employ.Remove (db.employ.Find (ID1))
Carter Medlin

2
@CarterMedlin - ในขณะที่ใช้งานได้จะเป็นสองฐานข้อมูล: หนึ่ง SELECT และหนึ่ง DELETE คนส่วนใหญ่พบว่าสิ้นเปลืองอย่างยิ่งโดยเฉพาะอย่างยิ่งการเลือกอาจใช้เวลามากกว่าการลบ
Davor

ฉันจะไม่แนะนำให้ใช้เฟรมเวิร์กเอนทิตี Remove หรือ RemoveRange เนื่องจากปัญหาด้านประสิทธิภาพ ฉันอยากจะใช้สิ่งที่ง่ายสุด ๆ ดังต่อไปนี้: var sql = "ลบจาก YOUR_TABLE WHERE YOUR_FIELD = @your_parameter"; this.your_context.Database.ExecuteSqlCommand (sql, SqlParameter ใหม่ ("@ your_parameter", yourParameter));
อยากรู้อยากเห็นบอย

2
@crownBoy ฉันคิดว่าเมื่อคุณดำเนินการตามที่คุณแนะนำแคช EF6 ไม่ได้สะท้อนการเปลี่ยนแปลง
Yitzchak

คำตอบ:


362

ไม่จำเป็นต้องค้นหาวัตถุก่อนคุณสามารถแนบกับบริบทด้วยรหัส แบบนี้:

var employer = new Employ { Id = 1 };
ctx.Employ.Attach(employer);
ctx.Employ.Remove(employer);
ctx.SaveChanges();

หรือคุณสามารถตั้งค่าสถานะของรายการที่แนบเป็นลบ:

var employer = new Employ { Id = 1 };
ctx.Entry(employer).State = EntityState.Deleted;
ctx.SaveChanges();

87
หรือมิctx.Entry(employer).State = EntityState.Deleted
ฉะนั้น

12
สิ่งนี้จะใช้ได้ก็ต่อเมื่อมีการกำหนดความสัมพันธ์เป็นลบทั้งหมด มิฉะนั้นรหัสด้านบนจะล้มเหลวในข้อยกเว้น FK
baruchl

6
@mt_serg ฉันกำลังมองไปข้างหน้า 3 ขั้นตอน ครั้งสุดท้ายที่คุณต้องลบบันทึกง่าย ๆ ออกจากฐานข้อมูลคืออะไร? โดยปกติแล้วคุณกำลังจัดการกับบันทึกที่ซับซ้อนมากขึ้นซึ่งรวมถึงความสัมพันธ์ FK ดังนั้นความคิดเห็นของฉัน
บารุค

2
@IanWarburton บรรทัดที่ 2 และ 3 (แนบและลบ)
Simon Belanger

4
@PaulZahra: บางครั้งคุณมีรายการ ID จากการสืบค้นหรือแหล่งอื่น ๆ และคุณต้องลบออก แทนที่จะโหลดวัตถุเพียงเพื่อลบวัตถุด้วยวิธีนี้คุณสามารถลบโดยใช้ ID คุณรู้ไหมว่านั่นเป็นวิธีที่คำสั่ง DELETE ทำงานใน SQL ตามปกติ
siride

82

คุณสามารถใช้SingleOrDefaultเพื่อรับวัตถุชิ้นเดียวที่ตรงกับเกณฑ์ของคุณแล้วส่งต่อไปยังRemoveวิธีการของตาราง EF ของคุณ

var itemToRemove = Context.Employ.SingleOrDefault(x => x.id == 1); //returns a single item.

if (itemToRemove != null) {
    Context.Employ.Remove(itemToRemove);
    Context.SaveChanges();
}

5
นี่ไม่ใช่วิธีที่ดีเพราะคุณเลือกทุกฟิลด์จากฐานข้อมูล!
Ali Yousefi

2
นี่คือวิธีที่ฉันทำ
แจ็คแฟร์ฟิลด์

4
@Ali, Jack - แต่ฉันคิดว่ามันดีกว่าเพราะจะตรวจสอบก่อนว่าข้อมูลที่คุณพยายามลบมีอยู่จริงหรือไม่ซึ่งสามารถป้องกันปัญหาใด ๆ ได้ คำตอบที่ยอมรับไม่มีการตรวจสอบเช่นนี้
Michael Philips

4
นี่เป็นวิธีที่ดีกว่า ลองคิดดู เกิดอะไรขึ้นถ้า John Smith พยายามลบรายการที่มี id = 1 ที่ Susie Smith นำออก 30 วินาทีที่แล้ว แต่ John ไม่รู้ คุณต้องกดฐานข้อมูลในกรณีนั้น
Yusha

5
@ Yusha ทำไม ในทั้งสองสถานการณ์ผลลัพธ์คือบันทึกหายไป เราสนใจจริง ๆ หรือไม่ว่ามันเกิดขึ้นตอนนี้หรือ 30 วินาทีก่อน เงื่อนไขการแข่งขันบางอย่างนั้นไม่ใช่สิ่งที่น่าสนใจในการติดตาม
9Rune5

13
  var stud = (from s1 in entities.Students
            where s1.ID== student.ID
            select s1).SingleOrDefault();

  //Delete it from memory
  entities.DeleteObject(stud);
  //Save to database
  entities.SaveChanges();

2
FirstOrDefaultอันตราย. อย่างใดอย่างหนึ่งคุณรู้ว่ามีเพียงคนเดียว (เพื่อใช้SingleOrDefault) หรือมีมากกว่าหนึ่งและมันควรจะทำในวง
Mark Sowul

8
Employer employer = context.Employers.First(x => x.EmployerId == 1);

context.Customers.DeleteObject(employer);
context.SaveChanges();

สิ่งนี้จะป้องกันหากไม่มีวัตถุที่มี Id 1 หรือไม่ มันจะไม่เกิดข้อยกเว้นใช่ไหม
แจ็คแฟร์ฟิลด์

@ JackFairfield ฉันคิดว่าคุณควรตรวจสอบวัตถุว่าง และตามที่มันดำเนินการลบ
Jawand Singh

Firstอันตราย. อย่างใดอย่างหนึ่งคุณรู้ว่ามีเพียงคนเดียว (เพื่อใช้Single) หรือมีมากกว่าหนึ่งและมันควรจะทำในวง
Mark Sowul

5

ฉันใช้กรอบงานเอนทิตีกับ LINQ รหัสต่อไปนี้มีประโยชน์สำหรับฉัน;

1- สำหรับหลายระเบียน

 using (var dbContext = new Chat_ServerEntities())
 {
     var allRec= dbContext.myEntities;
     dbContext.myEntities.RemoveRange(allRec);
     dbContext.SaveChanges();
 }

2- สำหรับบันทึกเดียว

 using (var dbContext = new Chat_ServerEntities())
 {
     var singleRec = dbContext.ChatUserConnections.FirstOrDefault( x => x.ID ==1);// object your want to delete
     dbContext.ChatUserConnections.Remove(singleRec);
     dbContext.SaveChanges();
 }

สำหรับบันทึกโสดทำไมไม่ใช้SingleOrDefaultแทนFirstOrDefault?
Mark Sowul

เมื่อใดก็ตามที่คุณใช้ SingleOrDefault คุณจะต้องระบุอย่างชัดเจนว่าการสืบค้นนั้นควรให้ผลลัพธ์เดียว ในทางกลับกันเมื่อใช้ FirstOrDefault แบบสอบถามสามารถส่งคืนจำนวนผลลัพธ์ใด ๆ แต่คุณระบุว่าคุณต้องการหนึ่งstackoverflow.com/a/1745716/3131402
Baqer Naqvi

1
ใช่แล้วทำไมมันถูกต้องที่จะลบเร็กคอร์ดโดยพลการถ้ามีมากกว่าหนึ่ง? โดยเฉพาะอย่างยิ่งในกรณีนี้ประชาชนได้เป็นกุญแจสำคัญเพื่อให้มีควรจะเป็นหนึ่ง: ถ้ามีมากกว่าหนึ่งมันเป็นข้อผิดพลาด (ซึ่งโสดจะตรวจสอบ)
มาร์ค Sowul

@ MarkSowul คุณถูกต้อง ฉันได้แก้ไขคำตอบเพื่อใช้ FirstOrDefault
Baqer Naqvi

@BaqerNaqvi RemoveRange เป็นวิธีที่ยอดเยี่ยมในการลบเอนทิตีออกจากมุมมองประสิทธิภาพการทำงาน .. โดยเฉพาะอย่างยิ่งเมื่อเอนทิตีของคุณหนักด้วยคุณสมบัติการนำทางทั้งหมดโดยคีย์ต่างประเทศ ฉันต้องการใช้ var sql = "ลบจาก YOUR_TABLE โดยที่ YOUR_FIELD = @your_parameter"; this.your_context.Database.ExecuteSqlCommand (sql, SqlParameter ใหม่ ("@ your_parameter", yourParameter));
อยากรู้อยากเห็นบอย

2

approuch ทั่วไปเพิ่มเติม

public virtual void Delete<T>(int id) where T : BaseEntity, new()
{
    T instance = Activator.CreateInstance<T>();
    instance.Id = id;
    if (dbContext.Entry<T>(entity).State == EntityState.Detached)
    {
        dbContext.Set<T>().Attach(entity);
    }

    dbContext.Set<T>().Remove(entity);
}

2

ด้วย Entity Framework 6 Removeคุณสามารถใช้ นอกจากนี้ยังเป็นกลยุทธ์ที่ดีที่จะใช้usingเพื่อให้แน่ใจว่าการเชื่อมต่อของคุณถูกปิด

using (var context = new EmployDbContext())
{
    Employ emp = context.Employ.Where(x => x.Id == id).Single<Employ>();
    context.Employ.Remove(emp);
    context.SaveChanges();
}

1

แค่อยากมีส่วนร่วมในสามวิธีที่ฉันได้ตีกลับไปมาด้วย

วิธีที่ 1:

var record = ctx.Records.FirstOrDefault();
ctx.Records.Remove(record);
ctx.SaveChanges();

วิธีที่ 2:

var record = ctx.Records.FirstOfDefault();
ctx.Entry(record).State = EntityState.Deleted;
ctx.SaveChanges();
ctx.Entry(record).State = EntityState.Detached;

หนึ่งในเหตุผลที่ฉันชอบไปกับวิธีที่ 2คือในกรณีที่ตั้งค่า EF หรือ EFCore QueryTrackingBehavior.NoTrackingเป็นวิธีที่ปลอดภัยกว่า

แล้วมีวิธีที่ 3:

var record = ctx.Records.FirstOrDefault();
var entry = ctx.Entry(record);
record.DeletedOn = DateTimeOffset.Now;
entry.State = EntityState.Modified;
ctx.SaveChanges();
entry.State = EntityState.Detached;

วิธีนี้ใช้วิธีการลบแบบนุ่มนวลโดยการตั้งค่าDeletedOnคุณสมบัติของเรกคอร์ดและยังคงสามารถเก็บบันทึกสำหรับใช้ในอนาคตสิ่งที่เคยเป็น โดยทั่วไปการวางไว้ใน Recycle Bin


นอกจากนี้เกี่ยวกับวิธีที่ 3แทนการตั้งค่าระเบียนทั้งหมดให้ถูกแก้ไข:

entry.State = EntityState.Modified;

นอกจากนี้คุณยังสามารถตั้งค่าเฉพาะคอลัมน์DeletedOnที่ถูกแก้ไข:

entry.Property(x => x.DeletedOn).IsModified = true;

0
    [HttpPost]
    public JsonResult DeleteCotnact(int id)
    {
        using (MycasedbEntities dbde = new MycasedbEntities())
        {
            Contact rowcontact = (from c in dbde.Contact
                                     where c.Id == id
                                     select c).FirstOrDefault();

            dbde.Contact.Remove(rowcontact);
            dbde.SaveChanges();

            return Json(id);
        }
    }

คุณคิดอย่างไรกับเรื่องนี้ง่าย ๆ หรือไม่คุณสามารถลองสิ่งนี้ได้:

        var productrow = cnn.Product.Find(id);
        cnn.Product.Remove(productrow);
        cnn.SaveChanges();

0

สำหรับ DAO ทั่วไปผลงานของฉัน finnaly นี้:

    public void Detele(T entity)
    {
        db.Entry(entity).State = EntityState.Deleted;
        db.SaveChanges();
    }


0

คุณสามารถทำมันได้อย่างนี้

   public ActionResult Delete(int? id)
    {
        using (var db = new RegistrationEntities())
        {
            Models.RegisterTable Obj = new Models.RegisterTable();
            Registration.DAL.RegisterDbTable personalDetail = db.RegisterDbTable.Find(id);
            if (personalDetail == null)
            {
                return HttpNotFound();
            }
            else
            {
                Obj.UserID = personalDetail.UserID;
                Obj.FirstName = personalDetail.FName;
                Obj.LastName = personalDetail.LName;
                Obj.City = personalDetail.City;

            }
            return View(Obj);
        }
    }


    [HttpPost, ActionName("Delete")]

    public ActionResult DeleteConfirmed(int? id)
    {
        using (var db = new RegistrationEntities())
        {
            Registration.DAL.RegisterDbTable personalDetail = db.RegisterDbTable.Find(id);
            db.RegisterDbTable.Remove(personalDetail);
            db.SaveChanges();
            return RedirectToAction("where u want it to redirect");
        }
    }

แบบ

 public class RegisterTable
{

    public int UserID
    { get; set; }


    public string FirstName
    { get; set; }


    public string LastName
    { get; set; }


    public string Password
    { get; set; }


    public string City
    { get; set; }

} 

ดูจากสิ่งที่คุณจะเรียกมันว่า

 <table class="table">
    <tr>
        <th>
            FirstName
        </th>
        <th>
            LastName
        </th>

        <th>
            City
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td> @item.FirstName </td>
            <td> @item.LastName </td>
            <td> @item.City</td>
            <td>
                <a href="@Url.Action("Edit", "Registeration", new { id = item.UserID })">Edit</a> |
                <a href="@Url.Action("Details", "Registeration", new { id = item.UserID })">Details</a> |
                <a href="@Url.Action("Delete", "Registeration", new { id = item.UserID })">Delete</a>

            </td>
        </tr>

    }

</table>

ฉันหวังว่ามันจะง่ายสำหรับคุณที่จะเข้าใจ


0

คุณสามารถทำสิ่งนี้ในการคลิกหรือเหตุการณ์ celldoubleclick ของตารางของคุณ (ถ้าคุณใช้)

if(dgEmp.CurrentRow.Index != -1)
 {
    employ.Id = (Int32)dgEmp.CurrentRow.Cells["Id"].Value;
    //Some other stuff here
 }

จากนั้นทำสิ่งนี้ในปุ่มลบของคุณ:

using(Context context = new Context())
{
     var entry = context.Entry(employ);
     if(entry.State == EntityState.Detached)
     {
        //Attached it since the record is already being tracked
        context.Employee.Attach(employ);
     }                             
     //Use Remove method to remove it virtually from the memory               
     context.Employee.Remove(employ);
     //Finally, execute SaveChanges method to finalized the delete command 
     //to the actual table
     context.SaveChanges();

     //Some stuff here
}

อีกวิธีหนึ่งคุณสามารถใช้ LINQ Query แทนการใช้ LINQ กับ Entities Query:

var query = (from emp in db.Employee
where emp.Id == employ.Id
select emp).Single();

ลูกจ้างใช้เป็นพารามิเตอร์การกรองซึ่งถูกส่งผ่านจากเหตุการณ์ CellDoubleClick ของ DataGridView ของคุณแล้ว


แนวคิดเบื้องหลังรหัสคือคุณโยงรหัส (จ้าง ID) ของระเบียนที่คุณต้องการลบไปยังรุ่น (ระดับพนักงาน) แล้วแนบไปกับตารางจริงจากบริบทจากนั้นดำเนินการลบในหน่วยความจำ ในที่สุดก็ทำการบันทึกจริงไปยังฐานข้อมูลโดยใช้วิธีการ SaveChanges () แม้ว่า LINQ Query ก็ใช้งานได้ดี แต่ฉันไม่ชอบความคิดในการสืบค้นในตารางเพียงเพื่อให้ได้ ID ของบันทึก
arvin aquio

0

นี่เป็นวิธีที่ปลอดภัย:

using (var transitron = ctx.Database.BeginTransaction())
{
  try
  {
    var employer = new Employ { Id = 1 };
    ctx.Entry(employer).State = EntityState.Deleted;
    ctx.SaveChanges();
    transitron.Commit();
  }
  catch (Exception ex)
  {
    transitron.Rollback();
    //capture exception like: entity does not exist, Id property does not exist, etc...
  }
}

ที่นี่คุณสามารถรวมการเปลี่ยนแปลงทั้งหมดที่คุณต้องการเพื่อให้คุณสามารถทำการลบชุดก่อน SaveChanges and Commit ดังนั้นการเปลี่ยนแปลงเหล่านั้นจะถูกนำไปใช้เฉพาะเมื่อประสบความสำเร็จทั้งหมด


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.