I've been using NHibernate (with Fluent-NHibernate mappings) in a project for the first time over the last few weeks, all was going well until today when I've hit a problem (most probably my own error).
I've made a small sample to illustrate what I'm trying to achieve:
public class Image
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Path { get; set; }
}
public class FeaturedImage
{
public virtual int Id { get; set; }
public virtual Image Image { get; set; }
public virtual string Description { get; set; }
public virtual DateTime Date { get; set; }
}
public class ImageMap : ClassMap<Image>
{
public ImageMap()
{
Id(x => x.Id).GeneratedBy.Identity().UnsavedValue(0);
Map(x => x.Name);
Map(x => x.Path);
}
}
public class FeaturedImageMap : ClassMap<FeaturedImage>
{
public FeaturedImageMap()
{
Id(x => x.Id).GeneratedBy.Identity().UnsavedValue(0);
Map(x => x.Description);
Map(x => x.Date);
References(x => x.Image).Not.Nullable().Cascade.Delete();
}
}
In the example above there are multiple images, each day one image gets picked as a "featured" image, the same image can be featured multiple times. The behaviour I would like is when I delete an image any FeaturedImage entries referencing that image ID automatically get deleted. However, at the moment if I try to delete an Image which has been featured it throws an error:
The DELETE statement conflicted with the REFERENCE constraint "FKF42D8269692640D". Conflict table "dbo.FeaturedImage", column 'Image_id'.
If If manually add "ON DELETE CASCADE" to the image id foreign key constraint it works:
alter table [FeaturedImage]
add constraint FKF42D8269692640D foreign key ( Image_id ) references [Image] ON DELETE CASCADE
...but I'm not sure if this is the recommended way of doing this? If anyone could advise the best way of achieving this it would be greatly appreciated! Thanks in advance.
Use the ON DELETE CASCADE option to specify whether you want rows deleted in a child table when corresponding rows are deleted in the parent table. If you do not specify cascading deletes, the default behavior of the database server prevents you from deleting data in a table if other tables reference it.
A foreign key with cascade delete means that if a record in the parent table is deleted, then the corresponding records in the child table will automatically be deleted.
Yes, the use of ON DELETE CASCADE is fine, but only when the dependent rows are really a logical extension of the row being deleted. For example, it's OK for DELETE ORDERS to delete the associated ORDER_LINES because clearly, you want to delete this order, which consists of a header and some lines.
1) ON DELETE CASCADE means if the parent record is deleted, then any referencing child records are also deleted. ON UPDATE defaults to RESTRICT, which means the UPDATE on the parent record will fail.
The .Cascade.Delete()
you added is in the wrong side of the relationship, and it would actually cause the Image to be deleted when you delete a FeaturedImage.
What you want to do can be accomplished by creating a collection of FeaturedImage in Image, map it as an inverse bag with cascade-deleting in the key.
I don't use Fluent, but in XML you set on-delete="cascade"
in the collection <key>
element; look for something similar.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With