2009-02-02 23 views
39

Tôi khá chắc chắn tôi đã nhìn thấy câu trả lời cho câu hỏi này ở đâu đó, nhưng như tôi không thể tìm thấy nó với một vài tìm kiếm trên SO hoặc google, tôi hỏi lại ...Làm cách nào để xóa một đối tượng khỏi mô hình Khung thực thể mà không tải nó trước?

Trong khuôn khổ thực thể , cách duy nhất để xóa đối tượng dữ liệu có vẻ là

MyEntityModel ent = new MyEntityModel(); 
ent.DeleteObject(theObjectToDelete); 
ent.SaveChanges(); 

Tuy nhiên, phương pháp này yêu cầu đối tượng được tải vào, trong trường hợp này là Bộ điều khiển trước, chỉ cần xóa đối tượng đó. Có cách nào để xóa một đối tượng nghiệp vụ chỉ tham chiếu cho ID của nó không?

Nếu có cách thông minh hơn bằng cách sử dụng biểu thức LINQ hoặc Lambda, điều đó cũng tốt. Mục tiêu chính, tuy nhiên, là để tránh tải dữ liệu chỉ để xóa nó.

+2

có một cách để làm cái này đẹp và thông thường: http://j.mp/f0x0Bh – BritishDeveloper

+0

@BritishDeveloper: Thú vị! Tuy nhiên, tôi có sau khi câu hỏi này được yêu cầu nhận ra rằng thường có nguyên nhân tốt để lấy thực thể đầu tiên, ít nhất là nếu có quan hệ ngoại giao quan trọng liên quan. –

+0

Bản sao có thể có của [Cách xóa đối tượng theo id với khung thực thể] (http://stackoverflow.com/questions/2471433/how-to-delete-an-object-by-id-with-entity-framework) –

Trả lời

19

Đó là giá trị biết rằng khung Entity hỗ trợ cả để LINQ to Entities và Entity SQL. Nếu bạn thấy mình muốn xóa hoặc cập nhật có khả năng ảnh hưởng đến nhiều bản ghi bạn có thể sử dụng tương đương với ExecuteNonQuery.

Trong Entity SQL này có thể trông như

Using db As New HelloEfEntities 

     Dim qStr = "Delete " & _ 
        "FROM Employee" 
     db.ExecuteStoreCommand(qStr) 
     db.SaveChanges() 
    End Using 

Trong ví dụ này, dbObjectContext tôi. Cũng lưu ý rằng hàm ExecuteStoreCommand có một mảng tham số tùy chọn.

+2

Câu trả lời này đi trực tiếp đến điểm mà người hỏi muốn làm và phải được đánh dấu là câu trả lời được chấp nhận. Các giải pháp khác như xây dựng thực thể từ không có gì là ít tối ưu. Ngoài ra, hãy kiểm tra điều này http://msdn.microsoft.com/en-us/library/ee358769.aspx – mare

+17

Tại sao bạn gọi SaveChanges sau ExecuteStoreCommand? – epotter

+7

Chuỗi ma thuật! Ugh. – mayu

8

Tôi đã tìm thấy this post, trong đó nói rằng thực sự không có cách nào tốt hơn để xóa bản ghi. Lời giải thích được đưa ra là tất cả các khóa ngoại, quan hệ, vv là duy nhất cho hồ sơ này cũng bị xóa, và vì vậy EF cần có thông tin chính xác về hồ sơ. Tôi bối rối vì lý do tại sao điều này không thể đạt được mà không cần tải dữ liệu qua lại, nhưng vì nó sẽ không xảy ra rất thường xuyên, tôi đã quyết định (bây giờ) rằng tôi sẽ không bận tâm.

Nếu bạn không có một giải pháp cho vấn đề này, cảm thấy tự do để cho tôi biết =)

+3

Làm thế nào về việc sử dụng một thủ tục lưu sẵn? –

4

Xin lỗi trước, nhưng tôi phải đặt câu hỏi về mục tiêu của bạn.

Nếu bạn xóa một đối tượng mà không bao giờ đọc nó, bạn không thể biết người dùng khác đã thay đổi đối tượng trong khoảng thời gian bạn xác nhận rằng bạn muốn xóa đối tượng và xóa thực tế. Trong "SQL cũ đơn giản", điều này sẽ giống như đang thực hiện:

DELETE FROM FOO 
WHERE ID = 1234 

Tất nhiên, hầu hết mọi người không thực sự làm điều này. Thay vào đó, họ làm điều gì đó như:

DELETE FROM FOO 
WHERE ID = 1234 
    AND NAME = ?ExpectedName AND... 

Vấn đề là xóa sẽ thất bại (không làm gì) nếu người dùng khác đã thay đổi bản ghi trong thời gian đó.

Với điều này, tuyên bố tốt hơn về vấn đề này, có hai giải pháp khả thi khi sử dụng Khuôn khổ thực thể.

  1. Trong phương thức Xóa, phiên bản hiện tại, so sánh giá trị mong đợi của thuộc tính và xóa nếu chúng giống nhau. Trong trường hợp này, khung Entity sẽ xử lý việc viết câu lệnh DELETE bao gồm các giá trị thuộc tính.

  2. Viết một thủ tục được lưu trữ chấp nhận cả giá trị IDE và các giá trị thuộc tính khác và thực hiện điều đó.

+1

Đó là một mục tiêu hoàn toàn hợp lệ nếu đối tượng của bạn không bao giờ được sửa đổi trong suốt vòng đời của họ và/hoặc truy vấn của bạn để TÌM các đối tượng để xóa ngụ ý tất cả các thuộc tính mà bạn sẽ xác minh đã có giá trị chính xác. –

4

Có cách để giả mạo tải thực thể bằng cách tính lại EntityKey của nó. Nó trông giống như một chút của một hack, nhưng có thể là cách duy nhất để làm điều này trong EF.

Blog bài viết về Deleting without Fetching

3
var toDelete = new MyEntityModel{ 
    GUID = guid, 
    //or ID = id, depending on the key 
    }; 
Db.MyEntityModels.Attach(toDelete); 
Db.MyEntityModels.DeleteObject(toDelete); 
Db.SaveChanges(); 

Trong trường hợp khóa của bạn chứa nhiều cột, bạn cần cung cấp tất cả các giá trị (ví dụ: GUID, columnX, columnY, v.v.).

Bạn cũng có thể xem here để biết chức năng chung nếu bạn cảm thấy điều gì đó lạ mắt.

+0

Đây là cách tốt nhất (tôi gọi nó bằng cách sử dụng một đối tượng giữ chỗ) nhưng nó không bị các mối quan tâm tương tranh đồng thời được đưa ra bởi Stuntz dưới đây. – dansan

3

Với khung pháp nhân 5 có Entity Framework Extended Library. Có sẵn trên NuGet. Sau đó, bạn có thể viết một cái gì đó như:

context.Users.Delete(u => u.Id == id); 

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

+0

Đây là một thư viện đáng kinh ngạc! Cảm ơn –

4

Bạn có thể tạo một đối tượng với cùng id và vượt qua nó thông qua các delete NHƯNG tốt của mình cho các đối tượng đơn giản nếu bạn có mối quan hệ phức tạp, bạn có thể cần nhiều hơn thế

   var user = new User { ID = 15 }; 
       context.Entry(user).State = EntityState.Deleted; 
       context.SaveChanges(); 
Các vấn đề liên quan