sorry I attached the wrong mapping file :-(
On Sat, May 30, 2009 at 12:29 AM, Yaojian <sky...@gmail.com> wrote: > Yes, the constructor is better in simplicity, and is slightly better in > performance if it is public :-) > > If you wanna to use the constructor solution, note that all auto-properties > must be replaced by a normal property with a backend field. for example: > > public String Name { get; set; } > > must be replaces with a normal property like: > > private String m_Name; > > public String Name { get { return m_Name;} set { m_Name = value;}} > > and the constructor should set the value to the "m_Name" field instead of > the property. > > > > On Sat, May 30, 2009 at 12:21 AM, Michael McCurrey <mmccur...@gmail.com>wrote: > >> Constructor loading is simple and no magic required. make sure your using >> the 1.6.2 source if your using maps that extend maps.... >> in your contructor you can then specific Isdirty = false as the last line; >> >> >> >> On Fri, May 29, 2009 at 8:45 AM, 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 >> > >
<?xml version="1.0" encoding="utf-8" ?> <!--============================================================================ // CAUTION: This file is generated by IBatisNetGen.BatisMap.cst at 2007/4/24 18:25:56 // Any manual editing will be lost in re-generation. //===========================================================================--> <sqlMap namespace="IdNameMap" xmlns="http://ibatis.apache.org/mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <cacheModels> <cacheModel id="cm" implementation="MEMORY" readOnly="true" serialize="false"> <flushInterval hours="24"/> <property name="CacheSize" value="10000"/> <flushOnExecute statement="InsertObject"/> <flushOnExecute statement="DeleteObject"/> <flushOnExecute statement="UpdateObject"/> </cacheModel> </cacheModels> <resultMaps> <resultMap id="rm" class="IdName"> <result property="Id" column="Id" dbType="Int"/> <result property="Name" column="Name" dbType="VarChar"/> </resultMap> </resultMaps> <statements> <select id="GetCount" resultClass="System.Int32"> SELECT count(*) FROM dbo.IdName </select> <sql id="Find"> SELECT * FROM dbo.IdName </sql> <select id="FindAll" resultMap="rm" cacheModel="cm"> <include refid="Find"/> </select> <select id="FindByPrimaryKey" resultMap="rm" parameterClass="Guid" extends="FindAll" cacheModel="cm"> WHERE (Id = #value,dbType=Int#) </select> <insert id="InsertObject" parameterClass="IdName"> INSERT INTO dbo.IdName ( Id , Name ) VALUES ( #Id,dbType=Int# , #Name,dbType=VarChar# ) </insert> <update id="UpdateObject" parameterClass="IdName"> UPDATE dbo.IdName SET Name = #Name,dbType=VarChar# WHERE (Id = #Id,dbType=Int#) </update> <delete id="DeleteObject" parameterClass="IdName"> DELETE FROM dbo.IdName WHERE (Id = #Id,dbType=Int#); </delete> </statements> </sqlMap>