2012-10-02 6 views
8

Tôi đang cố triển khai tính năng xóa mềm trong dự án của mình bằng cách ghi đè phương pháp DbContext.SaveChanges() và hoàn tác việc xóa bất kỳ đối tượng nào triển khai giao diện ISoftDelete của tôi.Ghi đè đối tượng ghi đè với các liên kết

interface ISoftDelete 
{ 
    bool IsDeleted { get; set; } 
} 

Trong SaveChanges() phương pháp tôi kêu gọi phương pháp SoftDelete() của tôi cho mỗi entry đó là trong 'xóa' nhà nước và thực hiện ISoftDelete:.

var entries = this.ChangeTracker.Entries().Where(x => (x.State == EntityState.Deleted) && x.Entity is ISoftDelete) 
        .ToList(); 
       entries.ForEach(SoftDelete); 

phương pháp SoftDelete() của tôi là như sau:

private void SoftDelete(DbEntityEntry entry) 
{ 
    if (entry.State == EntityState.Deleted && entry.Entity is ISoftDelete) 
    { 
     entry.Reload(); 
     var entity = (ISoftDelete)entry.Entity; 
     entity.IsDeleted = true; 
     entry.State = EntityState.Modified; 
    } 
} 

Điều này sẽ hoạt động hoàn hảo cho đến khi tôi chạy vào thực thể có liên kết một với một thứ khác. Tại thời điểm đó, ngoại lệ được ném với lỗi này:

{"A relationship from the 'ChildParent' AssociationSet is in the 'Deleted' state. Given multiplicity constraints, a corresponding 'Parent' must also in the 'Deleted' state."}

Có cách nào để có được tất cả các liên kết cho thực thể đó và thay đổi trạng thái đã xóa cho chúng không?

Tôi đã cố gắng nhận tham chiếu đến thực thể được liên kết thực tế nhưng đối tượng của EntityState được đặt thành Unchanged thay vì Deleted.

+3

Tôi nghĩ rằng sự kết hợp chính nó đang được đánh dấu là đã xóa (các liên kết được coi là các đối tượng riêng biệt trong EF) nhưng không được coi là thực thể liên quan. Bây giờ khi EF cố gắng để loại bỏ các hiệp hội nó không thể bởi vì các thực thể liên quan không được đánh dấu cho xóa. Tôi giả định rằng khóa ngoài không phải là nullable và do đó loại bỏ một thực thể yêu cầu loại bỏ các thực thể liên quan (cascade delete). Bạn có thể kiểm tra chủ đề này: http://stackoverflow.com/questions/10300156/ivalidatableobject-is-useless-for-ef-navigation-properties/10304323#10304323. Nó có thể hữu ích vì nó cho thấy làm thế nào để có được các đối tượng liên quan. – Pawel

+0

Rất hữu ích khi nhận các đối tượng liên quan, cảm ơn bạn. Tuy nhiên, khi cố gắng thay đổi trạng thái của một trong các mối quan hệ, tôi nhận được một lỗi lạ nói rằng "Không thể thay đổi trạng thái của một mối quan hệ nếu một trong những kết thúc của mối quan hệ là một KeyEntry." – Jonathan

+0

Bạn đã xem [giải pháp này] (http://connect.microsoft.com/VisualStudio/feedback/details/513174/unable-to-refresh-some-items-in-the-objectcontext) chưa? –

Trả lời

0

Nói chung, trước tiên bạn cần phải xóa các con trong mối quan hệ Cha-con. Bắt đầu với cha mẹ trên cùng, và tái khám theo cách của bạn thông qua các trẻ em. Đánh dấu mọi mục đã truy cập để bạn có thể theo dõi nếu nó đã bị xóa mềm (trong trường hợp tham chiếu ngược).

Nếu bạn có khái niệm "đối tượng doanh nghiệp", bạn có thể thêm các thuộc tính ChildsParent để dễ điều hướng. Nếu không, bạn sẽ phải "tay mã" này trên mỗi phụ huynh với quan hệ trẻ em không tầm thường.

Cũng lưu ý rằng việc sử dụng một câu lệnh LINQ bạn không thể kiểm soát việc duyệt ngang thực tế.

Tôi biết ở trên có vẻ như rất nhiều công việc, nhưng hãy xem xét cách bạn sẽ thiết bị một cơ chế trong EF sẽ tự động suy ra thông tin quan hệ cần thiết ?! Bạn sẽ kết thúc công việc như thế này.