Xóa một bản ghi từ Entity Framework?


195

Tôi có một bảng SQL Server trong Entity Framework được đặt tên employvới một cột khóa duy nhất có tên ID.

Làm cách nào để xóa một bản ghi khỏi bảng bằng Entity Framework?


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

2
@CarterMedlin - trong khi đó sẽ hoạt động, đó là hai lần truy cập cơ sở dữ liệu: một CHỌN và một XÓA. Hầu hết mọi người thấy rằng vô cùng lãng phí, đặc biệt là khi chọn có thể sẽ mất nhiều thời gian hơn so với xóa.
Thưởng thức

Tôi sẽ không đề xuất sử dụng khung thực thể Remove hoặc RemoveRange do các vấn đề về hiệu suất. Tôi thà chỉ sử dụng một cái gì đó siêu đơn giản như sau: var sql = "XÓA TỪ TỪ KHÓA CỦA BẠN WHERE YOU_FIELD = @your_parameter"; this .your_context.Database.ExecuteSqlCommand (sql, SqlParameter mới ("@ your_parameter", yourParameter));
tò mòBoy

2
@cantlyBoy Tôi nghĩ rằng khi bạn thực hiện các câu lệnh như bạn đề xuất, bộ đệm của EF6 không phản ánh sự thay đổi.
Yitzchak

Câu trả lời:


362

Không cần thiết phải truy vấn đối tượng trước, bạn có thể đính kèm nó vào ngữ cảnh theo id của nó. Như thế này:

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

Ngoài ra, bạn có thể đặt trạng thái của mục nhập đính kèm thành bị xóa:

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

87
Ngoài ra,ctx.Entry(employer).State = EntityState.Deleted
Simon Belanger

12
điều này sẽ chỉ hoạt động nếu các mối quan hệ được xác định là xóa tầng. nếu không, đoạn mã trên sẽ thất bại với ngoại lệ FK.
baruchl

6
@mt_serg, tôi đang tìm kiếm 3 bước phía trước. Lần cuối cùng bạn thực sự phải xóa một bản ghi đơn giản như vậy khỏi DB là khi nào? thông thường bạn đang xử lý các hồ sơ phức tạp hơn bao gồm các mối quan hệ FK. do đó nhận xét của tôi.
baruchl

2
@IanWarburton Dòng thứ 2 và 3 (Đính kèm và xóa)
Simon Belanger

4
@PaulZahra: đôi khi bạn có một danh sách ID từ một số truy vấn hoặc nguồn khác và bạn cần xóa một ID. Thay vì tải lên các đối tượng chỉ để xóa chúng, bằng cách này bạn có thể xóa bằng ID. Bạn biết đấy, đó là cách câu lệnh DELETE hoạt động bình thường trong SQL.
siride

82

Bạn có thể sử dụng SingleOrDefaultđể có được một đối tượng phù hợp với tiêu chí của mình và sau đó chuyển đối tượng đó sang Removephương thức của bảng EF.

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

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

5
Đây không phải là cách tốt, bởi vì bạn đang chọn tất cả các trường từ cơ sở dữ liệu!
Ali Yousefi

2
Đây là cách tôi làm.
Jack Fairfield

4
@Ali, Jack - Nhưng tôi nghĩ điều này là tốt hơn bởi vì trước tiên nó sẽ kiểm tra xem dữ liệu bạn đang cố xóa có thực sự tồn tại hay không có thể ngăn chặn mọi rắc rối. Câu trả lời được chấp nhận không có kiểm tra như vậy.
Michael Philips

4
Đây là cách tốt hơn. Hãy suy nghĩ về nó. Điều gì sẽ xảy ra nếu John Smith đang cố xóa một mục có id = 1 mà Susie Smith đã xóa 30 giây trước nhưng John không biết? Bạn cần phải nhấn cơ sở dữ liệu trong trường hợp đó.
Yusha

4
@Yusha Tại sao? Trong cả hai kịch bản, kết quả là bản ghi đã biến mất. Chúng ta có thực sự quan tâm nếu điều đó xảy ra bây giờ hoặc 30 giây trước? Một số điều kiện cuộc đua chỉ là không thú vị để theo dõi.
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
FirstOrDefaultlà nguy hiểm. Hoặc bạn biết chỉ có một (nên sử dụng SingleOrDefault), hoặc có nhiều hơn một, và nó nên được thực hiện trong một vòng lặp.
Mark Sowul

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

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

Điều này có bảo vệ nếu không có đối tượng với Id 1 không? Nó sẽ không ném một ngoại lệ?
Jack Fairfield

@JackFairfield tôi nghĩ bạn nên kiểm tra đối tượng null. và theo nó thực hiện loại bỏ.
Jawand Singh

Firstlà nguy hiểm. Hoặc bạn biết chỉ có một (nên sử dụng Single), hoặc có nhiều hơn một, và nó nên được thực hiện trong một vòng lặp.
Mark Sowul

5

Tôi đang sử dụng khung thực thể với LINQ. Mã sau đây là hữu ích cho tôi;

1- Đối với nhiều hồ sơ

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

2- Đối với hồ sơ đơn

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

Đối với bản ghi đơn tại sao không sử dụng SingleOrDefaultthay vì FirstOrDefault?
Mark Sowul

Bất cứ khi nào bạn sử dụng SingleOrDefault, bạn đều nêu rõ rằng truy vấn sẽ dẫn đến tối đa một kết quả. Mặt khác, khi FirstOrDefault được sử dụng, truy vấn có thể trả về bất kỳ số lượng kết quả nào nhưng bạn nói rằng bạn chỉ muốn một stackoverflow.com/a/1745716/3131402
Baqer Naqvi

1
Có, vậy tại sao nó lại chính xác để xóa một bản ghi tùy ý, nếu có nhiều hơn một? Đặc biệt trong trường hợp này, id là chìa khóa, vì vậy cần có một: nếu có nhiều hơn một, đó là một lỗi (mà Single sẽ phát hiện)
Mark Sowul

@MarkSowul bạn nói đúng. Tôi đã chỉnh sửa câu trả lời để sử dụng FirstOrDefault.
Baqer Naqvi

@BaqerNaqvi RemoveRange là cách khủng khiếp để xóa thực thể khỏi phối cảnh hiệu suất .. Đặc biệt khi thực thể của bạn nặng với tất cả các thuộc tính điều hướng bằng khóa ngoại. Tôi thà sử dụng var sql = "XÓA TỪ CỦA BẠN_TABLE WHERE YOU_FIELD = @your_parameter"; this .your_context.Database.ExecuteSqlCommand (sql, SqlParameter mới ("@ your_parameter", yourParameter));
tò mòBoy

2

Approuch chung hơn

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

Với Entity Framework 6, bạn có thể sử dụng Remove. Ngoài ra, đó là một chiến thuật tốt để sử dụng usingđể đảm bảo rằng kết nối của bạn được đóng lại.

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

1

Chỉ muốn đóng góp ba phương pháp mà tôi đã trả lại.

Cách 1:

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

Cách 2:

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

Một trong những lý do tại sao tôi thích đi cùng Phương pháp 2 là vì trong trường hợp cài đặt EF hoặc EFCore QueryTrackingBehavior.NoTracking, sẽ an toàn hơn khi thực hiện.

Sau đó, có Phương pháp 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;

Điều này sử dụng cách tiếp cận xóa mềm bằng cách thiết lập thuộc tính của bản ghi DeletedOnvà vẫn có thể giữ bản ghi để sử dụng trong tương lai, điều đó có thể xảy ra. Về cơ bản, đặt nó vào Thùng rác .


Ngoài ra, liên quan đến Phương pháp 3 , thay vì đặt toàn bộ hồ sơ thành sửa đổi:

entry.State = EntityState.Modified;

Bạn cũng chỉ cần đặt cột DeletedOnnhư đã sửa đổi:

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

Bạn nghĩ gì về điều này, đơn giản hay không, bạn cũng có thể thử điều này:

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

0

Đối với DAO chung, công việc của tôi hoàn thiện điều này:

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


0

bạn có thể làm nó đơn giản như thế này

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

mô hình

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

} 

xem từ đó bạn sẽ gọi nó

 <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>

tôi hy vọng điều này sẽ dễ dàng cho bạn hiểu


0

Bạn có thể làm một cái gì đó như thế này trong sự kiện nhấp chuột hoặc celldoubleclick của lưới của bạn (nếu bạn đã sử dụng một)

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

Sau đó làm một cái gì đó như thế này trong Nút Xóa của bạn:

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
}

Ngoài ra, bạn có thể sử dụng Truy vấn LINQ thay vì sử dụng Truy vấn LINQ To Thực thể:

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

Employ.Id được sử dụng làm tham số lọc đã được truyền từ Sự kiện CellDoubleClick của DataGridView của bạn.


Ý tưởng đằng sau mã là bạn kết nối id (Employ.Id) của bản ghi mà bạn muốn xóa vào mô hình (Lớp nhân viên) và sau đó đính kèm nó vào Bảng thực tế từ Ngữ cảnh sau đó thực thi Phương thức xóa () trong bộ nhớ cuối cùng thực hiện lưu thực tế vào cơ sở dữ liệu bằng Phương thức SaveChanges (). Mặc dù Truy vấn LINQ cũng hoạt động tốt nhưng tôi không thích ý tưởng truy vấn vào bảng chỉ để lấy id của bản ghi.
arvin aquio

0

Đây là một cách an toàn:

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...
  }
}

Tại đây, bạn có thể chồng tất cả các thay đổi bạn muốn, vì vậy bạn có thể thực hiện một loạt xóa trước SaveChanges và Cam kết, vì vậy chúng sẽ chỉ được áp dụng nếu tất cả đều thành công.


0

Cách tốt nhất là kiểm tra và sau đó xóa

        if (ctx.Employ.Any(r=>r.Id == entity.Id))
        {
            Employ rec = new Employ() { Id = entity.Id };
            ctx.Entry(rec).State = EntityState.Deleted;
            ctx.SaveChanges();
        }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.