nHibernate object mappings create key violations
Got a bit of an odd situation which I'm trying to map in Fluent nHibernate and failing. I have an Asset object which contains both an Image object and a File object. The Id of Image and File is identical, and the Image object contains a File object. This situation arises because an Image is always also a File (which is why the Id's have to match) but a File is not always an image.
I've mapped this as follows:
AssetMap
Public Sub New()
Id(Function(x) x.Id)
Map(Function(x) x.DisplayOrder)
Map(Function(x) x.Text).Length(10000)
Map(Function(x) x.Title)
Map(Function(x) x.Width)
Map(Function(x) x.Height)
References(Function(x) x.Image).LazyLoad().Cascade.All()
References(Function(x) x.File).LazyLoad().Cascade.All()
References(Function(x) x.Row).Cascade().All()
Map(Funct开发者_运维知识库ion(x) x.AssetType).CustomType(Of AssetType)()
End Sub
ImageMap
Public Sub New()
Id(Function(x) x.ID)
Map(Function(x) x.Height)
Map(Function(x) x.Width)
Map(Function(x) x.AltText)
Map(Function(x) x.ToolTip)
Map(Function(x) x.ImageStatus).CustomType(Of ImageStatus)()
References(Function(x) x.Product).Nullable()
HasOne(Function(x) x.File).Constrained()
References(Function(x) x.ViewTag)
HasManyToMany(Function(x As Image) x.ProductOptionValues).Table("ImageVsProductOptionValues").LazyLoad().Cascade.All()
HasManyToMany(Function(x As Image) x.MappedCategories).Table("CategoryVsImage").LazyLoad().Cascade.All().Inverse()
End Sub
Filemap
Public Sub New()
Id(Function(x) x.Id)
Map(Function(x) x.Data).LazyLoad().Length(Integer.MaxValue)
Map(Function(x) x.MimeType)
Map(Function(x) x.Size)
Map(Function(x) x.Filename)
Map(Function(x) x.LastDateModified)
Map(Function(x) x.DateCreated)
End Sub
I've run into trouble trying to use the following code to create a new image and add it to an Asset and save it.
If oAsset.Image Is Nothing Then
currentImage = New CMS.DataTransferObjects.Image
currentFile = New CMS.DataTransferObjects.File
Else
currentImage = oAsset.Image
currentFile = oAsset.File
End If
currentFile.Data = ms.ToArray
currentFile.MimeType = mimeType
currentFile.Filename = filImgUpload.FileName
currentFile.Size = filImgUpload.ContentLength
currentImage.Width = CInt(Utils.Convert.ToInt64(UploadedImage.PhysicalDimension.Width))
currentImage.Height = CInt(Utils.Convert.ToInt64(UploadedImage.PhysicalDimension.Height))
If oAsset.Image Is Nothing Then
oAsset.Image = currentImage
oAsset.File = currentFile
Else
'currentImage = oAsset.Image
'currentFile = oAsset.File
End If
I then call an nHibernate manager and try up .Update the Asset, which results in the following error:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK30EBACDFED57EBE9". The conflict occurred in database "BDM1_TestBed", table "dbo.File", column 'Id'.
Can anyone help sort out this mess - I assume my mappings are wrong, but I'm not sure how to improve them?
Before I post my thoughts, I'd reccomend NHibernate Profiler, if you're not using it already. It's saved my butt countless times with mapping issues, and there's a free trial if you want to just try it out. Usually, in a situation like this, seeing the SQL generated by NHIbernate (via NHProf) has led me to the solution. Check it out here: http://www.nhprof.com/
As for my thoughts, It does look like your mapping is incomplete. Try adding ForeignKey to your AssetMap, like so:
References(Function(x) x.File)
.ForeignKey("Id")
.LazyLoad()
.Cascade.All()
You will probably need to do the same for the ImageMap
From what I recall, Fluent NHibernate will automatically use the convention "Tablename_Id" if you don't specify the name explicitly.
Hope that helps. Let me know if that doesn't do it.
精彩评论