I'm sure someone will correct me if this isn't accurate, but I believe you can accomplish your save with Session.Merge- i.e. it should copy your changes to a persistent copy of that entity so you can then save the persistent entity with your changes. (from that point on, you don't need the detached copy that made the round trip to the UI)
Good luck! On Thu, Feb 11, 2010 at 4:33 PM, CSLem <[email protected]> wrote: > But the session is closed between the Get and the commit since I am > trying to avoid the long running session. That is I Get the object, > close the session and hand the object to the presentation layer. At > some point the object is passed back to the data layer. > > As a result I have a detached object and need to open a new session > and attach the object to the new session that I have. Doesn't that > mean I have to call some save method or lock? I have tried lock and, > if the collections have been retrieved, I get a "dirty collection" > error. > > On Feb 11, 4:22 pm, Jason Meckley <[email protected]> wrote: > > if the parent is managing the child entity and the parent is retrieved > > from the database there is no reason to explicitly call any of the > > Save operations. NH will do this for you. example > > > > var id = 1; > > var nameOfChild = "Jason"; > > using(var tx = session.BeginTransaction()) > > { > > try > > { > > var parent = session.Get<Parent>(id); > > parent.Add(nameOfChild); > > tx.Commit(); > > } > > catch > > { > > tx.Rollback(); > > throw; > > } > > > > } > > > > where parent.Add looks like > > class Parent > > { > > private IList<Child>() children = new List<Child>(); > > > > public virtual void Add(string name) > > { > > var child = new Child{Name = name, Parent = this}; > > children.Add(child); > > } > > > > } > > > > On Feb 11, 4:59 pm, CSLem <[email protected]> wrote: > > > > > > > > > Sorry for the long delay. I am still struggling to get the maps > > > correct and SQL performing as I need. > > > > > I do add the child to the list. Right now, after some changes to > > > cascade options and logic I have the tests doing all three operations. > > > However, it only works in a long running session. > > > > > My simple view of the app is this: > > > 1) Get an object from the data layer. This starts with Parent so the > > > first object I get is the parent with no lazy collections loaded. > > > 2) Close the session > > > 3) Let the user do whatever with the parent object > > > 4) IF the user needs the collection or collections, open a new > > > session, retrieve the collections, close the session > > > 5) Let the user make necessary changes to Parent and Children > > > 6) When the user indicates they want to save open a new session, call > > > session.SaveOrUpdate(parent) and have the data layer cascade whatever > > > is changed. > > > > > I would assume this is how an httpsession is handled. I am not in a > > > web session but still don't want the session to remain open since the > > > users often open the application and leave it up all day, creating a > > > very long connection if I don't destroy the session after each action. > > > > > If I close the session after I get the object(s) then when I pass the > > > Parent back to the data layer and call SaveOrUpdate(parent) NHibernate > > > issues an UPDATE statement for every object in the graph - Parent and > > > EVERY child that has been retrieved. I have tried used > > > SaveOrUpdateCopy instead but then seem to have problems in my unit > > > test if I attempt to update the object twice. That is, get the Parent > > > and Children, update something on one of the Children, send it back to > > > the database. Update something on the Parent, send it back to the > > > database. At this point (using SaveOrUpdateCopy) I get a "row was > > > updated or deleted...." error. > > > > > I just can't seem to find the right combination of attributes and > > > method calls to do what I assume is a pretty normal process. > > > > > Here is a sample test. > > > > > Parent parent = CurrentSession.GetById(parentId); //includes logic to > > > open a session, retrieve and close > > > parent.Amplify(); //retrieves the child collection(s) using a > > > separate session, close > > > parent.child.comment = "NEW TEXT"; > > > parent.ApplyChanges(); //opens a session, calls > > > session.SaveOrUpdate(parent) > > > parent.someproperty = "New value"; > > > parent.ApplyChanges(); > > > > > The second ApplyChanges opens the session correctly but either fails > > > with the row was updated error (using SaveOrUpdateCopy) or issues > > > UPDATE statements for EVERY object in parent and child collections. > > > (using SaveOrUpdate). > > > > > Today I switched my timestamp to a version column thinking that maybe > > > the timestamp was not performing well as a concurrency check but the > > > behavior is still exactly the same. Short of opening a session when I > > > start the application and closing it when I am done I am not sure > > > where to go from here. > > > > > On Feb 5, 3:23 pm, Diego Mijelshon <[email protected]> wrote: > > > > > > You need to add the Child to ChildList. Otherwise, how would > NHibernate find > > > > it? > > > > > > Diego > > > > > > On Fri, Feb 5, 2010 at 13:07, CSLem <[email protected]> wrote: > > > > > I have what I think is a VERY simple mapping. This particular one > uses > > > > > DB generated Ids for all tables and, depending on how I set up > inverse/ > > > > > cascade I can get saves to work all the time but either inserts or > > > > > deletes fail. Insert sometimes fails with a Cannot insert NULL > value > > > > > in ChildId column or appears to work but issues no INSERT to the > SQL > > > > > database. When I get the inserts to work the deletes fail due to > the > > > > > foreign key relationship on the child. > > > > > > > I always want the Parent to manage the relationship to the DB. That > > > > > is, for this application, there is never a need to try to insert/ > > > > > update/delete except through the parent so when the update > statement > > > > > is issued it is always session.saveorupdate(Parent); I would expect > > > > > that to issue the necessary INSERT Parent..., INSERT Child...; etc > > > > > with the correct ID or the necessary UPDATE/DELETE statements. > > > > > > > I am using the NHibernate V2.1.0.4000 and NHibernate.Linq > V1.0.0.4000, > > > > > although I don't know that Linq matters on this side of the > equation. > > > > > > > The current classes/maps are as follows and this version manages > > > > > everything except the insert. > > > > > > > public class Parent { > > > > > public virtual int ParentId { get; set; } > > > > > public virtual DateTime? LastModified { get; set; } > > > > > public virtual IList<Child> ChildList { get; set; } > > > > > } > > > > > > > public class Child { > > > > > public virtual int ChildId { get; set; } > > > > > public virtual Parent Parent { get; set; } > > > > > public virtual DateTime? Created { get; set; } > > > > > public virtual string CreatedBy { get; set; } > > > > > public virtual CommentType CommentType { get; set; } > > > > > public virtual string Comment { get; set; } > > > > > public virtual DateTime? LastModified { get; set; } > > > > > } > > > > > > > <?xml version="1.0" encoding="utf-8" ?> > > > > > <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" > > > > > assembly="NewAssembly.Core" > > > > > namespace="NewAssembly.Core"> > > > > > > > <class name="Parent" table="t_Parent"> > > > > > <id name="ParentId" type="string" unsaved-value="0"> > > > > > <generator class="native"></generator> > > > > > </id> > > > > > <timestamp name="LastModified"/> > > > > > <bag name="ChildList" inverse="true” > cascade="all-delete-orphan"> > > > > > <key column="ParentId"/> > > > > > <one-to-many class="Child"/> > > > > > </bag> > > > > > </class> > > > > > </hibernate-mapping> > > > > > > > <class name="Child" table="t_Child"> > > > > > <id name="ChildId"> > > > > > <generator class="native"/> > > > > > </id> > > > > > <timestamp name="LastModified"/> > > > > > <property name="Created"/> > > > > > <property name="CreatedBy"/> > > > > > <property name="CommentType" column="Type"/> > > > > > <property name="Comment"/> > > > > > <many-to-one name="Parent" column="ParentId"/> > > > > > </class> > > > > > </hibernate-mapping> > > > > > > > When the Child object is constructed I do set the Parent property. > On > > > > > an insert, however, the ParentId is obviously not generated yet and > > > > > the call to session.SaveOrUpdate(Parent) issues an INSERT to SQL > for > > > > > the parent record and, depending on settings, either no INSERT for > the > > > > > child or an INSERT with a NULL value constraint error. > > > > > > > What am I missing to get all three operations (insert, save, > delete) > > > > > working? > > > > > > > -C- > > > > > > > -- > > > > > You received this message because you are subscribed to the Google > Groups > > > > > "nhusers" group. > > > > > To post to this group, send email to [email protected]. > > > > > To unsubscribe from this group, send email to > > > > > [email protected]<nhusers%[email protected]> > <nhusers%[email protected]<nhusers%[email protected]> > > > > > > > . > > > > > For more options, visit this group at > > > > >http://groups.google.com/group/nhusers?hl=en.-Hidequoted text - > > > > > > - Show quoted text -- Hide quoted text - > > > > - Show quoted text - > > -- > You received this message because you are subscribed to the Google Groups > "nhusers" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]<nhusers%[email protected]> > . > For more options, visit this group at > http://groups.google.com/group/nhusers?hl=en. > > -- You received this message because you are subscribed to the Google Groups "nhusers" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/nhusers?hl=en.
