Cách xóa một đối tượng theo id với khung thực thể


105

Đối với tôi, dường như tôi phải truy xuất một đối tượng trước khi xóa nó bằng khung thực thể như bên dưới

var customer = context.Customers.First(c => c.Id == 1);

context.DeleteObject(customer);

context.Savechanges();

Vì vậy, tôi cần phải nhấn cơ sở dữ liệu hai lần. Có cách nào dễ dàng hơn không?


j.mp/f0x0Bh là câu trả lời của bạn. Đây là một tốt đẹp và cách chung chung để làm việc đó
BritishDeveloper

Câu trả lời:


93

Trong Entity Framework 6, hành động xóa là Remove. Đây là một ví dụ

Customer customer = new Customer () { Id = id };
context.Customers.Attach(customer);
context.Customers.Remove(customer);
context.SaveChanges();

16
Tại sao Attach? Tại sao không chỉ RemoveSaveChanges?
runeks

3
Bạn phải đính kèm thực thể của mình trong ngữ cảnh bởi vì nếu không làm như vậy, bạn sẽ gặp lỗi khi xóa. EF chỉ có thể xóa các thực thể trong ngữ cảnh này
Pierre-Luc

3
@runeks theo hướng dẫn sử dụng, thực thể phải tồn tại trong ngữ cảnh trước khi có thể thực hiện thao tác Xóa. Xem tại đây docs.microsoft.com/en-us/dotnet/api/…
dwkd

1
Tôi không sử dụng tệp đính kèm và nó hoạt động tốt
ILIAS M. DOLAPO

58

Giống như @Nix với một thay đổi nhỏ được nhập mạnh:

Nếu bạn không muốn truy vấn nó, chỉ cần tạo một thực thể, rồi xóa nó.

                Customer customer = new Customer () { Id = id };
                context.Customers.Attach(customer);
                context.Customers.DeleteObject(customer);
                context.SaveChanges();

7
Không hoàn hảo vì nó ném ra một ngoại lệ nếu thiếu đối tượng: "DbUpdateConcurrencyException: Lưu trữ cập nhật, chèn hoặc xóa câu lệnh ảnh hưởng đến một số hàng không mong muốn (0)." Tôi muốn nó bỏ qua điều này, giống như một câu lệnh DELETE.
Dunc

xin lỗi, điều này gây ra xác thực không cần thiết và luôn được mong đợi!
Hamed Zakery Miab

32

Câu hỏi tương tự ở đây .

Với Entity Framework có EntityFramework-Plus (thư viện phần mở rộng).
Có sẵn trên NuGet. Sau đó, bạn có thể viết một cái gì đó như:

// DELETE all users which has been inactive for 2 years
ctx.Users.Where(x => x.LastLoginDate < DateTime.Now.AddYears(-2))
     .Delete();

Nó cũng hữu ích cho việc xóa hàng loạt.


36
Nó bất chấp lý do rằng bây giờ đây không phải là một phần của thư viện EF cốt lõi.
nathanchere

1
@FerretallicA - đồng ý.
acarlon

2
phương thức này đã lỗi thời khi sử dụng: context.Users.Where (user => user.Id == id) .Delete ();
Manuel

Nó không hoạt động với Azure SQL DataWarehouse do lỗi "Mệnh đề FROM hiện không được hỗ trợ trong câu lệnh DELETE.". Nhưng SQL thô như trong câu trả lời của Jonik hoạt động.
Michael Freidgeim

1
Có cần context.SaveChanges () không?
Tomas Kubes

23

Nếu bạn không muốn truy vấn nó, chỉ cần tạo một thực thể, sau đó xóa nó.

Customer customer  = new Customer() {  Id = 1   } ; 
context.AttachTo("Customers", customer);
context.DeleteObject(customer);
context.Savechanges();

6

Tôi đang sử dụng mã sau trong một trong các dự án của mình:

    using (var _context = new DBContext(new DbContextOptions<DBContext>()))
    {
        try
        {
            _context.MyItems.Remove(new MyItem() { MyItemId = id });
            await _context.SaveChangesAsync();
        }
        catch (Exception ex)
        {
            if (!_context.MyItems.Any(i => i.MyItemId == id))
            {
                return NotFound();
            }
            else
            {
                throw ex;
            }
        }
    }

Bằng cách này, nó sẽ truy vấn cơ sở dữ liệu hai lần chỉ khi một ngoại lệ xảy ra khi cố gắng xóa mục có ID được chỉ định. Sau đó, nếu mục không được tìm thấy, nó sẽ trả về một thông điệp có ý nghĩa; nếu không, nó chỉ ném lại ngoại lệ (bạn có thể xử lý điều này theo cách phù hợp hơn với trường hợp của mình bằng cách sử dụng các khối bắt khác nhau cho các loại ngoại lệ khác nhau, thêm nhiều kiểm tra tùy chỉnh hơn bằng cách sử dụng khối if, v.v.).

[Tôi đang sử dụng mã này trong dự án MVC .Net Core / .Net Core với Entity Framework Core.]


2

Tôi cho rằng truy vấn sql thô là cách nhanh nhất

public void DeleteCustomer(int id)
{
   using (var context = new Context())
   {
      const string query = "DELETE FROM [dbo].[Customers] WHERE [id]={0}";
      var rows = context.Database.ExecuteSqlCommand(query,id);
      // rows >= 1 - count of deleted rows,
      // rows = 0 - nothing to delete.
   }
}

19
Điều này đánh bại mục đích của việc sử dụng tính năng đối tượng được đánh máy mạnh trong EF.
LawMan

4
Điều này làm ảnh hưởng đến tiền mặt nhận dạng EF. Sau EF này sẽ vẫn trả lại cho bạn thực thể đã xóa của bạn.
epox

1
Nó hoạt động với Azure SQL DataWarehouse, trong khi các giải pháp khác thì không.
Michael Freidgeim

1
Nếu bạn đang làm điều này, bạn cũng có thể không sử dụng ORM. Tôi tưởng tượng rằng điều này sẽ làm tổn hại đến bộ nhớ cache EF.
Storm Muller

Kiểu này dễ bị tấn công SQL Injection. Trong ví dụ cụ thể này, bạn được bảo vệ vì biến là số nguyên, nhưng không bao giờ sử dụng mẫu này với biến chuỗi.
thelem

2

Câu trả lời của dwkd chủ yếu phù hợp với tôi trong lõi Entity Framework, ngoại trừ khi tôi thấy ngoại lệ này:

InvalidOperationException: Không thể theo dõi trường hợp của loại thực thể 'Khách hàng' vì trường hợp khác có cùng giá trị khóa cho {'Id'} đã được theo dõi. Khi đính kèm các thực thể hiện có, hãy đảm bảo rằng chỉ một cá thể thực thể có giá trị khóa nhất định được đính kèm. Cân nhắc sử dụng 'DbContextOptionsBuilder.EnableSensitiveDataLogging' để xem các giá trị khóa xung đột.

Để tránh ngoại lệ, tôi đã cập nhật mã:

Customer customer = context.Customers.Local.First(c => c.Id == id);
if (customer == null) {
    customer = new Customer () { Id = id };
    context.Customers.Attach(customer);
}
context.Customers.Remove(customer);
context.SaveChanges();

1

Một phiên bản nhỏ hơn (khi so sánh với những phiên bản trước):

var customer = context.Find(id);
context.Delete(customer);
context.SaveChanges();

Vui lòng cung cấp một số ngữ cảnh cho đoạn mã này và có lẽ một số giải thích về những gì nó hoạt động tốt hơn các câu trả lời khác còn lại trong thập kỷ qua.
miken32

1

Câu trả lời này thực sự được lấy từ khóa học của Scott Allen có tiêu đề ASP.NET MVC 5 Cơ bản. Tôi nghĩ tôi sẽ chia sẻ vì tôi nghĩ nó hơi đơn giản và trực quan hơn bất kỳ câu trả lời nào ở đây. Cũng lưu ý theo Scott Allen và các khóa đào tạo khác mà tôi đã thực hiện, phương pháp tìm là một cách tối ưu hóa để truy xuất tài nguyên từ cơ sở dữ liệu có thể sử dụng bộ nhớ đệm nếu nó đã được truy xuất. Trong mã này, tập hợp đề cập đến một DBSet của các đối tượng. Đối tượng có thể là bất kỳ loại đối tượng chung nào.

        var object = context.collection.Find(id);  
        context.collection.Remove(object);
        context.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.