Hi,
I've got a problem with Cascade behaviour all-delete-orphan.
In one session I load the container object (SomeContainer) with its Files and File data. Then I close the session and let the user do some changes. Let's say the user wants to delete a file. Ok - i remove it from the container:
Code:
//method in SomeContainer
public void RemoveFile(File file)
{
_files.Remove(file);
if (file.Id != 0)
{
file.Deleted = true;
removedFiles.Add(file);
FirePropertyChanged("Files");
}
}
and during the update:
Code:
//method in SomeContainer
protected override void OnUpdate()
{
//save files flaged as deleted
foreach (File file in removedFiles)
{
file.Save();
}
}
But then the NHibernate throws an exception saying that
"You may not dereference an collection with cascade="all-delete-orphan""
It is because I manually initialize the collection in the File class:
private IList<FileData> _fileDatas = new List<FileData>();
I've read some posts about it and I know that I shouldn't change the _fileDatas reference cause NH wants to track the changes to delete possible orphaned entities and when I change the ref it is unable to.
Seems like a good reason to me.
But what should I do when I want to create a new file? If I remove the private IList<FileData> _fileDatas = new List<FileData>(); in the File class, then by saying
File f = new File(); f.Data = someBinaryData; I would cause a NullRefEx.
So how can I create a new entity with properly initialized collection that has a cascade all-delete-orphan? I want to create both entities (File and FileData) first in memory and later choose whether to persist or discard (based on user action).
NHibernate version: 1.2 Mapping documents: Since I use ActiveRecord I'm posting my classes decorated with attributes
Code:
[ActiveRecord(SelectBeforeUpdate = true)]
public partial class SomeContainer
: MainActiveRecordBase<SomeContainer>,
INotifyPropertyChanged
{
//...
private IList<File> _files = new List<File>();
[HasMany(Cascade = ManyRelationCascadeEnum.All, Inverse = true, Where="Deleted = 0",
Access = PropertyAccess.NosetterCamelcaseUnderscore,
RelationType = RelationType.Bag)]
public IEnumerable<File> Files
{
get
{
return _files;
}
}
//...
}
[ActiveRecord(SelectBeforeUpdate=true, Where="Deleted = 0")]
public class File : MainActiveRecordBase<File>
{
//...
private IList<FileData> _fileDatas = new List<FileData>();
[HasManyAttribute(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan,
Access = PropertyAccess.NosetterCamelcaseUnderscore,
Lazy = true)]
private IList<FileData> FileDatas
{
get
{
return _fileDatas;
}
}
public byte[] Data
{
get
{
if (_fileDatas.Count == 0)
{
return null;
}
else
{
return _fileDatas[0].Data;
}
}
set
{
if (_fileDatas.Count == 0)
{
FileData fileData = new FileData();
fileData.File = this;
_fileDatas = new List<FileData>();
_fileDatas.Add(fileData);
}
_fileDatas[0].Data = value;
}
}
}
[ActiveRecord()]
public class FileData : MainActiveRecordBase<FileData>
{
private byte[] _data;
[Property(Column = "`Data`", ColumnType = "BinaryBlob", Length = 2147483647)]
public byte[] Data
{
get
{
return _data;
}
set
{
_data = value;
}
}
private File _file;
[BelongsTo("FileId")]
public File File
{
get
{
return _file;
}
set
{
_file = value;
}
}
}
Name and version of the database you are using:Oracle 10g XE[/code]