2010-03-31 28 views
33

Tôi sử dụng Entity Framework 4 và tôi có quan hệ cha - con với tập hợp "Cascade Delete". Vì vậy, tôi sẽ mong đợi khi tôi xóa một đứa trẻ khỏi cha mẹ mà đứa trẻ bị xóa khi tôi gọi SaveChanges().EF 4: Loại bỏ đối tượng con khỏi bộ sưu tập không xóa nó - tại sao?

 cuRepository.Attach(_controlUnit); 
     foreach (var recipe in recipes) { 
      _controlUnit.Recipes.Remove(recipe); 
      //repository.DeleteObject(recipe); 
     } 

Thay vào đó tôi nhận được một lỗi:

System.InvalidOperationException occurred Message=The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.

Khi tôi xóa một cách rõ ràng trẻ em (xem dòng nhận xét), tất cả đều tốt. Tôi đang thiếu gì?

+0

tôi đã cùng một vấn đề ngày hôm nay và tôi tin rằng đây là một lỗ hổng thiết kế trong Entity Framework. Mối quan hệ giữa các bảng trong SQL Server nói "Cascade delete orphans" và do đó sẽ hoạt động. Nó hoạt động như thế trong NHibernate. May mắn là bạn có thể làm cho nó hoạt động sau câu trả lời của GraemeMiller và các câu hỏi liên quan. –

Trả lời

28

Bạn không xóa đối tượng có tuyên bố xóa. Thay vào đó bạn đang cố gắng thay đổi một bản ghi và biến nó trở thành một đứa trẻ mồ côi (bằng cách thiết lập khóa ngoài thành null). Cơ sở dữ liệu có một ràng buộc không null trên cột đó và ngăn bạn làm như vậy.

+2

... vì vậy nếu đây là câu trả lời đúng thì mã nào được sử dụng để thực sự xóa mối quan hệ? –

+2

@ Ek0nomik ông nói: repository.DeleteObject (công thức); –

10

thêm context.DeleteObject(recipe) bên trong vòng lặp

26

http://weblogs.asp.net/zeeshanhirani/archive/2010/07/23/removing-entity-from-a-related-collection.aspx giải thích chính xác những gì đã xảy ra với bạn.


Giả sử bạn có một cái gì đó thiết kế lớp như thế này:

sample class design

Entity Framework sẽ tạo ra các cột chính nước ngoài theo yêu cầu và thêm NOT NULL trở ngại đối với họ bởi vì tất cả các thức nấu ăn sẽ luôn luôn được gắn liền với chính xác một ControlUnit.

Vì vậy, khi chạy bạn sẽ có các đối tượng tương tự như cách bố trí như sau:

object diagram at runtime

Bây giờ mã của bạn đến chơi và xóa các mối quan hệ giữa Recipe đối tượng và ControlUnit của họ:

objects with deleted relationships

Đang cố gắng lưu tại thời điểm này, cơ sở dữ liệu không có ID ControlUnit để đưa vào khóa ngoài NOT NULL cột. Trạng thái đối tượng hiện tại vi phạm sơ đồ lớp ở trên và không thể được lưu vào bố cục cơ sở dữ liệu đã được tạo theo giả định rằng mọi Công thức đều được liên kết với một ControlUnit. Đây là lý do tại sao cơ sở dữ liệu từ chối lưu các thay đổi và bạn thấy ngoại lệ.

Điều này cũng giải thích lý do tại sao nó hoạt động khi bạn bỏ ghi chú dòng xóa thực thể: Thực thể được loại bỏ khỏi cơ sở dữ liệu cùng với mối quan hệ của nó, do đó không có ràng buộc nào bị vi phạm.

"Nhưng tôi đặt ON DELETE CASCADE về mối quan hệ ..."

Vâng, nhưng điều đó chỉ được kích hoạt trên việc xóa đối tượng, không phải trên xóa của mối quan hệ.Với ON DELETE CASCADE bộ, điều này sẽ làm việc:

controlUnitRepository.DeleteObject(_controlUnit); 
// deletes the ControlUnit and all associated Recipe entities 

Nếu bạn muốn kích hoạt xoá các đối tượng Recipe về xóa mối quan hệ của họ với ControlUnit, mối quan hệ của bạn không phải là một hiệp hội đơn giản mà là một thành phần:

updated class diagram with composition

EF không hỗ trợ điều này nguyên bản, nhưng bạn có thể mô phỏng hành vi bằng cách sử dụng các mối quan hệ xác định. Khi thực thể nằm trong mối quan hệ xác định với thực thể cha và mối quan hệ đó bị xóa, thực thể cũng sẽ bị xóa. Có vẻ như đây là ý định của bạn ngay từ đầu. Để biết thêm thông tin về việc xác định mối quan hệ, hãy xem Implementing identifying relationships with EF4 nơi tôi đã triển khai các mối quan hệ xác định với EF4 và đã liên kết với nhiều tài liệu đọc hơn.

3

tôi sử dụng phần mở rộng này để không để thêm một phương pháp trong DAL chỉ để xóa một thực thể (mã lấy từ http://blogs.msdn.com/b/alexj/archive/2009/06/08/tip-24-how-to-get-the-objectcontext-from-an-entity.aspx):

public static void Delete<T>(this EntityCollection<T> collection, T entityToDelete) where T : EntityObject, IEntityWithRelationships 
{ 
    RelationshipManager relationshipManager = entityToDelete.RelationshipManager; 

    IRelatedEnd relatedEnd = relationshipManager.GetAllRelatedEnds().FirstOrDefault(); 
    if (relatedEnd == null) 
    { 
     throw new Exception("No relationships found for the entity to delete. Entity must have at least one relationship."); 
    } 

    var query = relatedEnd.CreateSourceQuery() as ObjectQuery; 
    if (query == null) 
    { 
     throw new Exception("The entity to delete is detached. Entity must be attached to an ObjectContext."); 
    } 

    query.Context.DeleteObject(entityToDelete); 
    collection.Remove(entityToDelete); 
} 

Vì vậy, tôi sau đó xóa một thực thể như Order.Products.Delete(prod).

Các hạn chế để sử dụng phần mở rộng là:
- Thực thể phải có mối quan hệ;
- Thực thể phải được gắn vào ObjectContext.

6

Nếu bạn thực hiện mối quan hệ giữa trẻ em và cha mẹ một xác định thì bạn có thể xóa các thực thể con khỏi bộ sưu tập. Bạn cần phải tạo khóa của con một khóa tổng hợp chứa khóa id chính của phụ huynh. Bằng cách đó, EF biết rằng nó cần phải loại bỏ đứa trẻ.

Xác định mối quan hệ về cơ bản nói rằng nếu cha mẹ không tồn tại thì trẻ không có ý nghĩa. Điều này có nghĩa là EF biết là an toàn khi xóa đứa trẻ khi mối quan hệ bị loại bỏ.

Xem câu hỏi này Identifying Relationship and inserting child entities causes "Cannot insert explicit value for identity column in table" và điều này một Is it possible to remove child from collection and resolve issues on SaveChanges?

+0

Xem thêm http://stackoverflow.com/questions/3710191/implementing-identifying-relationships-with-ef4 nơi tôi gặp sự cố này và giải thích cách tạo mối quan hệ xác định. Ngoài ra còn có một liên kết đến một bài đăng blog giải thích chi tiết này. – Chris

Các vấn đề liên quan