Elegant solution! For flexibility, It would be nice to do this either on a object alias basis or on a resultmap basis in the ibatis source.
On Fri, May 29, 2009 at 9:08 AM, Yaojian <sky...@gmail.com> wrote: > I have a new solution based on a custom ISetAccessor rather than the > IObjectFactory. > As the IBatisNet use ISetAccessor to set the value of a property, we can > use a custom ISetAccessor saves the IsDirty state before actually set the > property value and restore it later. > > I attach the unit test. > > Hope it works for you. > > > > On Fri, May 29, 2009 at 11:45 PM, Sal Bass <salbass...@hotmail.com> wrote: > >> >> I am using auto properties. I have toyed with ibatis constructor loading, >> but because I have never used it on a production app with Ibatis I have been >> hesitant. >> >> I may have to resort to using standard properties and go with Yaojin's >> solution, or your constructor solution. I have been trying to avoid both of >> these but there is no other way....that I can think of. >> >> >> >> ________________________________ >> > Date: Fri, 29 May 2009 08:35:46 -0700 >> > Subject: Re: Dirty Tracking Issue >> > From: mmccur...@gmail.com >> > To: user-cs@ibatis.apache.org >> > >> > Are you in a situation where you can't use constructor loading of your >> objects? If your not using auto-properties (which it seems your not), this >> might solve your problem entirely. >> > >> > On Fri, May 29, 2009 at 8:32 AM, Yaojian> wrote: >> > >> > That is my mistake, the nested objects loaded from the database is not >> touched so they remains its dirty state set by AOP. >> > >> > >> > I think the simplest solution is to map a column to a field instead of a >> property. >> > >> > for example, a C# property: >> > >> > >> > private string m_Name; >> > >> > public String Name >> > { >> > get { return m_Name; } >> > set { m_Name = value; } >> > } >> > >> > we can map the column "Name" to the "m_Name" field rather than the >> "Name" property in SqlMap: >> > >> > >> > >> > >> > >> > So load object from DB will not fire the dirty tracking injiected by >> AOP. >> > >> > >> > >> > >> > On Fri, May 29, 2009 at 9:19 PM, Sal Bass> wrote: >> > >> > >> > >> > >> > Yaojian, >> > >> > >> > >> > Thanks! I am still confused though. When I make a call to QueryForObject >> and reset the IsLoading flag to false, that only sets it false for the root >> object. All complex property collections that are loaded at the same time >> will not be reset. Am I missing something obvious? >> > >> > >> > >> > >> > >> > >> > >> > >> > >> > ________________________________ >> > >> >> Date: Fri, 29 May 2009 03:52:58 +0800 >> > >> >> Subject: Re: Dirty Tracking Issue >> > >> >> From: sky...@gmail.com >> > >> >> To: user-cs@ibatis.apache.org >> > >> >> >> > >> >> If the non-root object is loaded from the database, it should be >> created with the new object factory. >> > >> >> otherwise, it is irrelavant with 'dirty'. >> > >> >> >> > >> >> Bellow is my code for using IObjectFactory, I use a custom >> IObjectFactory for attaching each object to a context variable. >> > >> >> >> > >> >> >> > >> >> >> > >> >> DomSqlMapBuilder builder = CreateDomSqlMapBuilder(); >> > >> >> >> > >> >> //Use SqmObjectFactory for attaching objects to the current >> IObjectContext >> > >> >> IObjectFactory originalFactory = new ObjectFactory(true); >> > >> >> >> > >> >> SqmObjectFactory contextableFactory = new >> SqmObjectFactory(originalFactory); >> > >> >> builder.ObjectFactory = contextableFactory; >> > >> >> >> > >> >> ISqlMapper sqlMapper = builder.Configure(m_SqlMapDocument); >> > >> >> >> > >> >> >> > >> >> >> -------------------------------------------------------------------------------------------------------------------------------------------------- >> > >> >> >> > >> >> /// Represents the factory of MDA persistent object used by IBatis.NET. >> > >> >> >> > >> >> /// attaches an >> > >> >> /// to each objects created with this factory. >> > >> >> public class SqmObjectFactory : IObjectFactory, IEntityContextBindable >> > >> >> >> > >> >> { >> > >> >> /// Creates an instance. >> > >> >> /// The original . >> > >> >> public SqmObjectFactory(IObjectFactory objectFactoryImpl) >> > >> >> >> > >> >> { >> > >> >> if (objectFactoryImpl == null) throw new >> ArgumentNullException("objectFactoryImpl"); >> > >> >> m_ObjectFactoryImpl = objectFactoryImpl; >> > >> >> } >> > >> >> >> > >> >> private readonly IObjectFactory m_ObjectFactoryImpl; >> > >> >> >> > >> >> >> > >> >> private IEntityContext m_EntityContext; >> > >> >> >> > >> >> public IEntityContext EntityContext >> > >> >> { >> > >> >> get { return m_EntityContext; } >> > >> >> set { m_EntityContext = value; } >> > >> >> } >> > >> >> >> > >> >> >> > >> >> /// . >> > >> >> public IFactory CreateFactory(Type typeToCreate, Type[] types) >> > >> >> { >> > >> >> IFactory result = m_ObjectFactoryImpl.CreateFactory(typeToCreate, >> types); >> > >> >> >> > >> >> if (typeof(IEntityContextBindable).IsAssignableFrom(typeToCreate)) >> > >> >> { >> > >> >> return new SqmFactory(this, result); >> > >> >> } >> > >> >> return result; >> > >> >> } >> > >> >> >> > >> >> private class SqmFactory : IFactory >> > >> >> >> > >> >> { >> > >> >> public SqmFactory(IEntityContextBindable objectContextable, IFactory >> factory) >> > >> >> { >> > >> >> if (objectContextable == null) throw new >> ArgumentNullException("objectContextable"); >> > >> >> >> > >> >> if (factory == null) throw new ArgumentNullException("factory"); >> > >> >> >> > >> >> m_ObjectContextable = objectContextable; >> > >> >> m_Factory = factory; >> > >> >> } >> > >> >> >> > >> >> private readonly IEntityContextBindable m_ObjectContextable; >> > >> >> >> > >> >> >> > >> >> private readonly IFactory m_Factory; >> > >> >> >> > >> >> public object CreateInstance(object[] parameters) >> > >> >> { >> > >> >> Object result = m_Factory.CreateInstance(parameters); >> > >> >> ((IEntityContextBindable)result).EntityContext = >> m_ObjectContextable.EntityContext; >> > >> >> >> > >> >> return result; >> > >> >> } >> > >> >> } >> > >> >> } >> > >> >> >> > >> >> >> > >> >> On Fri, May 29, 2009 at 3:45 AM, Sal Bass> wrote: >> > >> >> >> > >> >> >> > >> >> >> > >> >> Yes, I explored that. But how will that work for the complex >> properties? Only the root object would know it's in a loading state. >> > >> >> >> > >> >> >> > >> >> >> > >> >> >> > >> >> >> > >> >> ________________________________ >> > >> >> >> > >> >>> Date: Fri, 29 May 2009 02:22:33 +0800 >> > >> >> >> > >> >>> Subject: Re: Dirty Tracking Issue >> > >> >> >> > >> >>> From: sky...@gmail.com >> > >> >> >> > >> >>> To: user-cs@ibatis.apache.org >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> We can bypass to set 'dirty' if the AOP generation mechanism can know >> an object is in 'loading' state. >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> We can use a custom IBatisNet.Common.Utilities.IObjectFactory to mark >> an object 'loading'. >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> And we can use a wrapped ISqlMapper to clean the 'loading' flag as: >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> public object QueryForObject(string statementName, object >> parameterObject) { >> > >> >> >> > >> >>> Object result = originalSqlMapper.QueryForObject(...); >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> result.IsLoading = false; >> > >> >> >> > >> >>> return result; >> > >> >> >> > >> >>> } >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> Yaojian >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> On Fri, May 29, 2009 at 1:55 AM, Sal Bass> wrote: >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> I am having a dilema with implementing dirty tracking on my entities. >> I am using AOP to mark an entity as "dirty" when a property is set. The >> problem occurs when I load the entities using Ibatis because it sets the >> properties during mapping which makes the entity dirty (no, I can't use >> constructor mapping here). So, I use a RowDelegate to mark the entity clean >> before returning it. Works great....except for when I am loading a root >> object with several complex properties (ILists of other entities). The >> RowDelegate is obviously not fired for each complex property, so they are >> returned as dirty. >> > >> > >> > >> >> >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> Any idea of how I can get at all of the complex properties to mark >> them clean before returning the entity? >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> _________________________________________________________________ >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> Hotmail® goes with you. >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> >> http://windowslive.com/Tutorial/Hotmail/Mobile?ocid=TXT_TAGLM_WL_HM_Tutorial_Mobile1_052009 >> > >> > >> > >> >> >> > >> >> >> > >> >>> >> > >> >> >> > >> >>> >> > >> >> >> > >> >> _________________________________________________________________ >> > >> >> >> > >> >> Windows Live™: Keep your life in sync. >> > >> >> >> > >> >> http://windowslive.com/explore?ocid=TXT_TAGLM_BR_life_in_synch_052009 >> > >> >> >> > >> > _________________________________________________________________ >> > >> > Insert movie times and more without leaving Hotmail®. >> > >> > >> http://windowslive.com/Tutorial/Hotmail/QuickAdd?ocid=TXT_TAGLM_WL_HM_Tutorial_QuickAdd1_052009 >> > >> > >> > >> > >> > >> > >> > >> > -- >> > Michael J. McCurrey >> > Read with me at http://www.mccurrey.com >> _________________________________________________________________ >> Windows Live™: Keep your life in sync. >> http://windowslive.com/explore?ocid=TXT_TAGLM_BR_life_in_synch_052009 >> > > -- Michael J. McCurrey Read with me at http://www.mccurrey.com