mlaen
mlaen

Reputation: 53

NHibernate HiLo doesn't generate ID on objects in collections

I'm using NHibernate and HiLo strategy and my problem is that IDs of objects in collections are not generated on Session.Save() (only on Transaction.Commit()). For example:

ImageGallery imageGallery = imageGalleryRepository.GetById(imgGalleryId);
imageGallery.Images.Add(new Image());
imageGalleryRepository.Save(imageGallery); // Here I need to access ID propery of new image in Images collection but it's 0 until I commit transaction. Can it be done?

Here's the code that I have:

public abstract class Entity
{
    public virtual int Id { get; set; }
}

public class ImageGallery : Entity
{
    public virtual IList<Image> Images { get; set; }
    // ...
}

public class Image : Entity
{
    public string FileName { get; set; }
    public ImageGallery ImageGallery { get; set; }
    // ...
}

Mappings:

public class ImageGalleryMap : ClassMap<ImageGallery>
{
    public ImageGalleryMap()
    {
        Id(x => x.Id).GeneratedBy.HiLo("hibernate_unique_key", "next_hi_image_gallery", "10");
        HasMany(x => x.Images).
            Cascade.All().
            KeyColumn("GalleryId").
            Inverse().
            Fetch.Join();
    }
}

public class GalleryImageMap : ClassMap<GalleryImage>
{
    public GalleryImageMap()
    {
        Id(x => x.Id).GeneratedBy.HiLo("hibernate_unique_key", "next_hi_image", "10");
        Map(x => x.FileName);
        References(x => x.ImageGallery).Column("GalleryId");
    }
}

Upvotes: 2

Views: 644

Answers (2)

Dave Rael
Dave Rael

Reputation: 1759

cascading changes for an existing object does not happen until you flush and go to the database. if you want to have a new object (the image) associated with the session, you need to add it to the session itself by calling save on the session and passing the new object. when you have a new gallery object you are adding to the session, it does traverse the object graph and add the referenced children.

also (not very important, but just to point out), you don't need to call save for the gallery itself that you already got from the session with getbyid. it's already there in the session and any changes to it will be persisted when the session flushes. save is really more of an operation to add something to the session. it doesn't care if you try to add something that is already there, it just doesn't really do anything.

Upvotes: 0

Cole W
Cole W

Reputation: 15303

Session.Save does not necessarily Flush the changes to the database. Session is a unit of work that contains database changes. It does not necessarily post the changes to the database right away. Please take a look at using Session.Flush(). Please read the following for a more detailed description:

http://www.nhforge.org/doc/nh/en/index.html#manipulatingdata-flushing

Edit:

When you have a bidirectional relationship you also want to maintain this from the code perspective. So you would need to do something like this:

ImageGallery imageGallery = imageGalleryRepository.GetById(imgGalleryId);
Image newImage = new Image();
newImage.ImageGallery = imageGallery;
imageGallery.Images.Add(newImage);

imageGalleryRepository.Save(imageGallery);

Generally I use Add/Remove methods in my entities to do this instead of explicitly doing it in the code above.

If this answer or any other answer here helps you please click the check mark marking it as the answer.

Upvotes: 2

Related Questions