2008-11-19 42 views
74

Tôi có một đối tượng cha mẹ có quan hệ một đến nhiều với một IList của các đối tượng con. Cách tốt nhất để xóa các đối tượng con là gì? Tôi không xóa phụ huynh. Đối tượng cha mẹ của tôi chứa một IList của các đối tượng con. Dưới đây là các bản đồ cho một đến nhiều mối quan hệ:Làm thế nào để xóa đối tượng con trong NHibernate?

<bag name="Tiers" cascade="all"> 
    <key column="mismatch_id_no" /> 
    <one-to-many class="TGR_BL.PromoTier,TGR_BL"/> 
</bag> 

Nếu tôi cố gắng để loại bỏ tất cả các đối tượng từ bộ sưu tập sử dụng rõ ràng(), sau đó gọi SaveOrUpdate(), tôi nhận được ngoại lệ này:

System.Data.SqlClient.SqlException: Cannot insert the value NULL into column 

Nếu tôi cố gắng để xóa các con đối tượng riêng rẽ sau đó loại bỏ chúng khỏi mẹ, tôi nhận được một ngoại lệ:

deleted object would be re-saved by cascade 

Đây là lần đầu tiên của tôi đối phó với việc xóa đối tượng trẻ em trong NHibernate. Tôi đang làm gì sai?

chỉnh sửa: Chỉ cần làm rõ - Tôi KHÔNG cố xóa đối tượng gốc, chỉ là đối tượng con. Tôi có mối quan hệ được thiết lập như một mối quan hệ với cha mẹ. Tôi cũng cần phải tạo mối quan hệ nhiều-với-một trên ánh xạ đối tượng con không?

Trả lời

130

Bạn đang gặp phải lỗi đầu tiên vì, khi bạn xóa các mục khỏi bộ sưu tập, chế độ mặc định của NHibernate hoạt động đơn giản là ngắt liên kết. Trong cơ sở dữ liệu, NHibernate cố gắng thiết lập cột khóa ngoài trên hàng con thành null. Vì bạn không cho phép null trong cột đó, SQL Server làm tăng lỗi. Việc xóa bộ sưu tập sẽ không nhất thiết phải xóa đối tượng con, nhưng một cách để làm như vậy là đặt cascade = all-delete-orphan. Điều này thông báo NHibernate rằng nó sẽ xóa các hàng mới mồ côi thay vì thiết lập cột khóa ngoài.

Bạn đang gặp lỗi thứ hai vì khi bạn gọi SaveOrUpdate NHibernate đầu tiên sẽ xóa tất cả các đối tượng con. Sau đó, vì không phải mối quan hệ nào được đánh dấu là nghịch đảo, NHibernate cũng cố gắng đặt cột khóa ngoài trong bảng con của bạn thành null. Vì các hàng đã bị xóa, bạn nhận được lỗi thứ hai. Bạn cần đặt nghịch đảo = true ở một bên của mối quan hệ của bạn để sửa lỗi này. Điều này thường được thực hiện trên một (khóa chính hoặc phụ huynh) bên. Nếu bạn không làm điều này, NHibernate sẽ làm cho các bản cập nhật thích hợp cho mỗi bên của mối quan hệ. Thật không may, chạy hai bản cập nhật không phải là điều thích hợp để làm.

Bạn phải luôn đánh dấu một bên mối quan hệ của mình là mặt nghịch đảo. Tùy thuộc vào cách bạn mã, bạn có thể hoặc có thể không cần phải sử dụng tầng. Nếu bạn muốn tận dụng lợi thế của một lần xóa khi bạn đang cố gắng sử dụng Clear(), bạn cần phải xác định tầng của bạn.

+0

Chỉ cần làm rõ - Tôi chỉ có mối quan hệ được xác định trên đối tượng Chánh ngay bây giờ. Tôi đã cố gắng để thiết lập các thác trên đối tượng đó để "tất cả" và "tất cả-xóa-mồ côi" với cùng một kết quả cả hai lần. Bạn có nghĩa là tôi cần phải xác định một mối quan hệ nhiều-một trong một đối tượng con? –

+0

Và trong trường hợp này không nghịch đảo = "true" thuộc về cha mẹ hoặc đối tượng con? –

+2

nó thuộc về lớp không giữ khóa ngoại ... thường là phụ huynh. – pmlarocque

-3

đặt Không-Null = đúng trong ánh xạ của bạn trên cột gây ra sự cố. Tôi không chắc chắn về cú pháp chính xác mặc dù (xin lỗi).

+0

Ok, tôi đặt cột thành không-null = "true" trên ánh xạ của đối tượng con. Vì vậy, tôi gọi phương thức clear() trên IList của các đối tượng con, sau đó thử SaveOrUpdate(). Tôi vẫn nhận được lỗi "Không thể chèn giá trị NULL vào cột". Tôi đang làm điều gì khác sai? –

+0

cột nào là lỗi được đưa lên? làm thế nào chính xác là bạn xóa các trẻ em trong mô hình của bạn? –

+0

Tôi đang gọi phương thức clear() trên đối tượng con Ilist trong đối tượng cha mẹ của tôi. Sau đó, tôi gọi SaveOrUpdate() trên phụ huynh. –

0

Thay đổi giá trị thuộc tính tầng từ "tất cả" thành "tất cả-xóa-trẻ mồ côi".

+0

Đã thử điều này. Tôi vẫn nhận được ngoại lệ tương tự. –

+16

all-delete-orphan xóa các trẻ em khi bạn xóa cha mẹ. nó không liên quan gì đến việc xóa những đứa trẻ như anh chàng này đang hỏi. –

2

Hãy thử sử dụng hợp nhất() thay vì saveOrUpdate(). Ngoài ra, hãy chắc chắn rằng thác của bạn được đặt thành all-delete-mồ côi và mối quan hệ cha-con của bạn không thể đảo ngược (inverse = true trên parent và sau đó một trường trong child là parent-id với not-null = true) .

2

Trong ví dụ của chúng tôi, chúng tôi có các danh mục có nhiều sản phẩm trong đó sản phẩm không thể rỗng.

Bạn có thể giải quyết vấn đề bằng cách xóa sản phẩm và xóa sản phẩm khỏi bộ sưu tập của cha mẹ trước khi xả nhưng chúng tôi vẫn đang tìm giải pháp tốt hơn cho điều này.

product = pRepo.GetByID(newProduct.ProductID); 
product.Category.Products.Remove(product); 
pRepo.Delete(product); 

Hy vọng nó giúp nào

+0

Điều này đòi hỏi một kho lưu trữ mặc dù. – UpTheCreek

3

Theo cách trả lời của Chuck, tôi đã giải quyết vấn đề của tôi bằng cách thêm Inverse = true trong cha mẹ bên lập bản đồ:

nhắn có nhiều MessageSentTo:

[HasMany(typeof(MessageSentTo), Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Inverse = true)] 
public IList<MessageSentTo> MessageSendTos 
{ 
    get { return m_MessageSendTo; } 
    set { m_MessageSendTo = value; } 
} 

Tôi đang sử dụng Castle ActiveRecord. Cảm ơn Chuck.

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