How do I merge a transient entity with a session using Castle ActiveRecordMediator?
- by Daniel T.
I have a Store and a Product entity:
public class Store
{
public Guid Id { get; set; }
public int Version { get; set; }
public ISet<Product> Products { get; set; }
}
public class Product
{
public Guid Id { get; set; }
public int Version { get; set; }
public Store ParentStore { get; set; }
public string Name { get; set; }
}
In other words, I have a Store that can contain multiple Products in a bidirectional one-to-many relationship.
I'm sending data back and forth between a web browser and a web service. The following steps emulates the communication between the two, using session-per-request.
I first save a new instance of a Store:
using (new SessionScope())
{
// this is data from the browser
var store = new Store { Id = Guid.Empty };
ActiveRecordMediator.SaveAndFlush(store);
}
Then I grab the store out of the DB, add a new product to it, and then save it:
using (new SessionScope())
{
// this is data from the browser
var product = new Product { Id = Guid.Empty, Name = "Apples" });
var store = ActiveRecordLinq.AsQueryable<Store>().First();
store.Products.Add(product);
ActiveRecordMediator.SaveAndFlush(store);
}
Up to this point, everything works well. Now I want to update the Product I just saved:
using (new SessionScope())
{
// data from browser
var product = new Product { Id = Guid.Empty, Version = 1, Name = "Grapes" };
var store = ActiveRecordLinq.AsQueryable<Store>().First();
store.Products.Add(product);
// throws exception on this call
ActiveRecordMediator.SaveAndFlush(store);
}
When I try to update the product, I get the following exception:
a different object with the same identifier value was already associated with the session: 00000000-0000-0000-0000-000000000000, of entity:Product"
As I understand it, the problem is that when I get the Store out of the database, it also gets the Product that's associated with it. Both entities are persistent. Then I tried to save a transient Product (the one that has the updated info from the browser) that has the same ID as the one that's already associated with the session, and an exception is thrown.
However, I don't know how to get around this problem. If I could get access to a NHibernate.ISession, I could call ISession.Merge() on it, but it doesn't look like ActiveRecordMediator has anything similar (SaveCopy threw the same exception). Does anyone know the solution? Any help would be greatly appreciated!