You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ibatis.apache.org by gb...@apache.org on 2007/01/04 22:28:11 UTC

svn commit: r492753 - in /ibatis/trunk/cs/mapper: IBatisNet.DataMapper.Test/Domain/ IBatisNet.DataMapper.Test/Maps/MSSQL/SqlClient/ IBatisNet.DataMapper.Test/NUnit/SqlMapTests/ IBatisNet.DataMapper/MappedStatements/PropertStrategy/ IBatisNet.DataMapper...

Author: gbayon
Date: Thu Jan  4 13:28:10 2007
New Revision: 492753

URL: http://svn.apache.org/viewvc?view=rev&rev=492753
Log:
- Fixed for iIBATISNET-182 : Allow lazy load on simple class

Modified:
    ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/Domain/Account.cs
    ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/Domain/Order.cs
    ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/Maps/MSSQL/SqlClient/Order.xml
    ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/NUnit/SqlMapTests/StatementTest.cs
    ibatis/trunk/cs/mapper/IBatisNet.DataMapper/MappedStatements/PropertStrategy/SelectGenericListStrategy.cs
    ibatis/trunk/cs/mapper/IBatisNet.DataMapper/MappedStatements/PropertStrategy/SelectListStrategy.cs
    ibatis/trunk/cs/mapper/IBatisNet.DataMapper/MappedStatements/PropertStrategy/SelectObjectStrategy.cs
    ibatis/trunk/cs/mapper/IBatisNet.DataMapper/Proxy/LazyFactoryBuilder.cs
    ibatis/trunk/cs/mapper/IBatisNet.DataMapper/Proxy/LazyLoadInterceptor.cs
    ibatis/trunk/cs/mapper/IBatisNet.DataMapper/Proxy/LazyLoadProxyFactory.cs

Modified: ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/Domain/Account.cs
URL: http://svn.apache.org/viewvc/ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/Domain/Account.cs?view=diff&rev=492753&r1=492752&r2=492753
==============================================================================
--- ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/Domain/Account.cs (original)
+++ ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/Domain/Account.cs Thu Jan  4 13:28:10 2007
@@ -35,7 +35,7 @@
             _document = document;
         }
 
-		public int Id
+		public virtual int Id
 		{
 			get { return id; }
 			set { id = value; }

Modified: ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/Domain/Order.cs
URL: http://svn.apache.org/viewvc/ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/Domain/Order.cs?view=diff&rev=492753&r1=492752&r2=492753
==============================================================================
--- ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/Domain/Order.cs (original)
+++ ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/Domain/Order.cs Thu Jan  4 13:28:10 2007
@@ -146,26 +146,14 @@
 
 		public string City
 		{
-			get
-			{
-				return _city; 
-			}
-			set
-			{ 
-				_city = value; 
-			}
+			get { return _city; }
+			set { _city = value; }
 		}
 
 		public string Street
 		{
-			get
-			{
-				return _street; 
-			}
-			set
-			{ 
-				_street = value; 
-			}
+			get { return _street; }
+			set { _street = value; }
 		}
 
 		public string CardExpiry
@@ -204,16 +192,10 @@
 			}
 		}
 
-		public Account Account
+		public virtual Account Account
 		{
-			get
-			{
-				return _account; 
-			}
-			set
-			{ 
-				_account = value; 
-			}
+			get { return _account; }
+			set { _account = value; }
 		}
 
 		public int Id

Modified: ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/Maps/MSSQL/SqlClient/Order.xml
URL: http://svn.apache.org/viewvc/ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/Maps/MSSQL/SqlClient/Order.xml?view=diff&rev=492753&r1=492752&r2=492753
==============================================================================
--- ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/Maps/MSSQL/SqlClient/Order.xml (original)
+++ ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/Maps/MSSQL/SqlClient/Order.xml Thu Jan  4 13:28:10 2007
@@ -151,6 +151,19 @@
       <result property="Province"   column="Order_Province"/>
       <result property="PostalCode" column="Order_PostalCode"/>
     </resultMap>
+
+    <resultMap id="order-JIRA182"  class="Order" >
+      <result property="Id"       column="Order_ID"/>
+      <result property="Account"  column="Account_ID" lazyLoad="true" select="GetAccountViaColumnName"/>
+      <result property="Date"       column="Order_Date"/>
+      <result property="CardExpiry" column="Order_CardExpiry"/>
+      <result property="CardType"   column="Order_CardType"/>
+      <result property="CardNumber" column="Order_CardNumber"/>
+      <result property="Street"     column="Order_Street"/>
+      <result property="City"       column="Order_City"/>
+      <result property="Province"   column="Order_Province"/>
+      <result property="PostalCode" column="Order_PostalCode"/>
+    </resultMap>
     
     <resultMap id="credit-card-result" class="string">
 			<result property="value" column="Order_CardNumber"/>
@@ -772,34 +785,32 @@
     <select id="GetOrderConstructor8"
 		parameterClass="Integer"
 		resultMap="order-result-constructor8">
-		select 
-			Order_ID, 
-			Order_Date, 
-			Order_CardExpiry, 
-			Order_CardType,
-			Order_CardNumber, 
-			Order_Street, 
-			Order_City, 
-			Order_Province, 
-			Order_PostalCode,
-			acc.Account_ID,
-			acc.Account_FirstName,
-			acc.Account_LastName,
-			acc.Account_Email,
-			acc.Account_Banner_Option,
-			acc.Account_Cart_Option
-		from Orders as ord
-		LEFT OUTER JOIN Accounts as acc on acc.Account_ID = ord.Account_ID
-		where Order_ID = #value#
-	</select>
-
-
+		  select 
+			  Order_ID, 
+			  Order_Date, 
+			  Order_CardExpiry, 
+			  Order_CardType,
+			  Order_CardNumber, 
+			  Order_Street, 
+			  Order_City, 
+			  Order_Province, 
+			  Order_PostalCode,
+			  acc.Account_ID,
+			  acc.Account_FirstName,
+			  acc.Account_LastName,
+			  acc.Account_Email,
+			  acc.Account_Banner_Option,
+			  acc.Account_Cart_Option
+		  from Orders as ord
+		  LEFT OUTER JOIN Accounts as acc on acc.Account_ID = ord.Account_ID
+		  where Order_ID = #value#
+	  </select>
 	
-	<select id="GetOrderConstructor9" 
-		extends="GetOrderConstructor8"
-		parameterClass="Integer"
-		resultMap="order-joined-with-account-constructor">
-	</select>
+	  <select id="GetOrderConstructor9" 
+		  extends="GetOrderConstructor8"
+		  parameterClass="Integer"
+		  resultMap="order-joined-with-account-constructor">
+	  </select>
     
     <select id="GetOrderConstructor10"
         parameterClass="Integer"
@@ -823,8 +834,26 @@
       from Orders as ord
       LEFT OUTER JOIN Accounts as acc on acc.Account_ID = ord.Account_ID
       where Order_ID = #value#
-    </select>	
-    
+    </select>
+
+    <select id="JIRA182"
+    parameterClass="Integer"
+    resultMap="order-JIRA182">
+      select
+      Order_ID,
+      Order_Date,
+      Order_CardExpiry,
+      Order_CardType,
+      Order_CardNumber,
+      Order_Street,
+      Order_City,
+      Order_Province,
+      Order_PostalCode,
+      Account_ID
+      from Orders
+      where Order_ID = #value#
+    </select>
+
   </statements>
 
 	<parameterMaps>   

Modified: ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/NUnit/SqlMapTests/StatementTest.cs
URL: http://svn.apache.org/viewvc/ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/NUnit/SqlMapTests/StatementTest.cs?view=diff&rev=492753&r1=492752&r2=492753
==============================================================================
--- ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/NUnit/SqlMapTests/StatementTest.cs (original)
+++ ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/NUnit/SqlMapTests/StatementTest.cs Thu Jan  4 13:28:10 2007
@@ -1225,6 +1225,19 @@
         #region JIRA Tests
 
         /// <summary>
+        /// Test a constructor argument with select tag.
+        /// </remarks>
+        [Test]
+        public void TestJIRA182()
+        {
+            Order order = sqlMap.QueryForObject("JIRA182", 5) as Order;
+
+            Assert.IsTrue(order.Id == 5);
+            Assert.IsNotNull(order.Account);
+            Assert.AreEqual(5, order.Account.Id);
+        }
+
+        /// <summary>
         /// QueryForDictionary does not process select property
         /// </summary>
         [Test]

Modified: ibatis/trunk/cs/mapper/IBatisNet.DataMapper/MappedStatements/PropertStrategy/SelectGenericListStrategy.cs
URL: http://svn.apache.org/viewvc/ibatis/trunk/cs/mapper/IBatisNet.DataMapper/MappedStatements/PropertStrategy/SelectGenericListStrategy.cs?view=diff&rev=492753&r1=492752&r2=492753
==============================================================================
--- ibatis/trunk/cs/mapper/IBatisNet.DataMapper/MappedStatements/PropertStrategy/SelectGenericListStrategy.cs (original)
+++ ibatis/trunk/cs/mapper/IBatisNet.DataMapper/MappedStatements/PropertStrategy/SelectGenericListStrategy.cs Thu Jan  4 13:28:10 2007
@@ -29,7 +29,6 @@
 using System.Data;
 
 using IBatisNet.DataMapper.Configuration.ResultMapping;
-using IBatisNet.DataMapper.Proxy;
 using IBatisNet.DataMapper.Scope;
 
 namespace IBatisNet.DataMapper.MappedStatements.PropertyStrategy

Modified: ibatis/trunk/cs/mapper/IBatisNet.DataMapper/MappedStatements/PropertStrategy/SelectListStrategy.cs
URL: http://svn.apache.org/viewvc/ibatis/trunk/cs/mapper/IBatisNet.DataMapper/MappedStatements/PropertStrategy/SelectListStrategy.cs?view=diff&rev=492753&r1=492752&r2=492753
==============================================================================
--- ibatis/trunk/cs/mapper/IBatisNet.DataMapper/MappedStatements/PropertStrategy/SelectListStrategy.cs (original)
+++ ibatis/trunk/cs/mapper/IBatisNet.DataMapper/MappedStatements/PropertStrategy/SelectListStrategy.cs Thu Jan  4 13:28:10 2007
@@ -27,7 +27,6 @@
 using System.Collections;
 using System.Data;
 using IBatisNet.DataMapper.Configuration.ResultMapping;
-using IBatisNet.DataMapper.Proxy;
 using IBatisNet.DataMapper.Scope;
 
 namespace IBatisNet.DataMapper.MappedStatements.PropertyStrategy

Modified: ibatis/trunk/cs/mapper/IBatisNet.DataMapper/MappedStatements/PropertStrategy/SelectObjectStrategy.cs
URL: http://svn.apache.org/viewvc/ibatis/trunk/cs/mapper/IBatisNet.DataMapper/MappedStatements/PropertStrategy/SelectObjectStrategy.cs?view=diff&rev=492753&r1=492752&r2=492753
==============================================================================
--- ibatis/trunk/cs/mapper/IBatisNet.DataMapper/MappedStatements/PropertStrategy/SelectObjectStrategy.cs (original)
+++ ibatis/trunk/cs/mapper/IBatisNet.DataMapper/MappedStatements/PropertStrategy/SelectObjectStrategy.cs Thu Jan  4 13:28:10 2007
@@ -64,8 +64,16 @@
 			postSelect.Target = target;
 			postSelect.ResultProperty = mapping;
 
-			postSelect.Method = PostBindind.ExecuteMethod.ExecuteQueryForObject;
-			request.QueueSelect.Enqueue(postSelect);
+			if (mapping.IsLazyLoad)
+			{
+				object values = mapping.LazyFactory.CreateProxy(selectStatement, keys, target, mapping.SetAccessor);
+				mapping.SetAccessor.Set(target, values);
+			}
+			else
+			{
+				postSelect.Method = PostBindind.ExecuteMethod.ExecuteQueryForObject;
+				request.QueueSelect.Enqueue(postSelect);
+			}
 		}
 
         /// <summary>

Modified: ibatis/trunk/cs/mapper/IBatisNet.DataMapper/Proxy/LazyFactoryBuilder.cs
URL: http://svn.apache.org/viewvc/ibatis/trunk/cs/mapper/IBatisNet.DataMapper/Proxy/LazyFactoryBuilder.cs?view=diff&rev=492753&r1=492752&r2=492753
==============================================================================
--- ibatis/trunk/cs/mapper/IBatisNet.DataMapper/Proxy/LazyFactoryBuilder.cs (original)
+++ ibatis/trunk/cs/mapper/IBatisNet.DataMapper/Proxy/LazyFactoryBuilder.cs Thu Jan  4 13:28:10 2007
@@ -38,7 +38,7 @@
     /// </summary>
     public class LazyFactoryBuilder
     {
-        IDictionary _factory = new HybridDictionary();
+        private IDictionary _factory = new HybridDictionary();
 
         /// <summary>
         /// Initializes a new instance of the <see cref="LazyFactoryBuilder"/> class.

Modified: ibatis/trunk/cs/mapper/IBatisNet.DataMapper/Proxy/LazyLoadInterceptor.cs
URL: http://svn.apache.org/viewvc/ibatis/trunk/cs/mapper/IBatisNet.DataMapper/Proxy/LazyLoadInterceptor.cs?view=diff&rev=492753&r1=492752&r2=492753
==============================================================================
--- ibatis/trunk/cs/mapper/IBatisNet.DataMapper/Proxy/LazyLoadInterceptor.cs (original)
+++ ibatis/trunk/cs/mapper/IBatisNet.DataMapper/Proxy/LazyLoadInterceptor.cs Thu Jan  4 13:28:10 2007
@@ -31,7 +31,9 @@
 using System.Reflection;
 using Castle.DynamicProxy;
 using IBatisNet.Common.Logging;
+using IBatisNet.Common.Utilities.Objects;
 using IBatisNet.Common.Utilities.Objects.Members;
+using IBatisNet.Common.Utilities.Proxy;
 using IBatisNet.DataMapper.MappedStatements;
 #if dotnet2
 using System.Collections.Generic;
@@ -51,10 +53,11 @@
 		private object _param = null;
 		private object _target = null;
 		private ISetAccessor _setAccessor= null;
-        private ISqlMapper _sqlMap = null;
+		private ISqlMapper _sqlMap = null;
 		private string _statementName = string.Empty;
 		private bool _loaded = false;
-		private IList _innerList = null;
+		private object _lazyLoadedItem = null;
+		//private IList _innerList = null;
 		private object _loadLock = new object();
 		private static ArrayList _passthroughMethods = new ArrayList();
 
@@ -69,7 +72,6 @@
 		static LazyLoadInterceptor()
 		{
 			_passthroughMethods.Add("GetType");
-			_passthroughMethods.Add("ToString");
 		}
 
 		/// <summary>
@@ -80,13 +82,13 @@
 		/// <param name="setAccessor">The proxified member accessor.</param>
 		/// <param name="target">The target object which contains the property proxydied.</param>
 		internal LazyLoadInterceptor(IMappedStatement mappedSatement, object param,
-            object target, ISetAccessor setAccessor)
+			object target, ISetAccessor setAccessor)
 		{
 			_param = param;
 			_statementName = mappedSatement.Id;
 			_sqlMap = mappedSatement.SqlMap;
 			_target = target;
-            _setAccessor = setAccessor;
+			_setAccessor = setAccessor;
 		}		
 		#endregion
 
@@ -113,13 +115,23 @@
 					{
 						_logger.Debug("Proxyfying call, query statement " + _statementName);
 					}
-					_innerList = _sqlMap.QueryForList(_statementName, _param);
+		
+					//Perform load
+                    if (typeof(IList).IsAssignableFrom(_setAccessor.MemberType))
+					{
+						_lazyLoadedItem = _sqlMap.QueryForList(_statementName, _param);
+					}
+					else
+					{
+						_lazyLoadedItem = _sqlMap.QueryForObject(_statementName, _param);
+					}
+
 					_loaded = true;
-                    _setAccessor.Set(_target, _innerList);
+					_setAccessor.Set(_target, _lazyLoadedItem);
 				}
 			}
 
-			object returnValue = invocation.Method.Invoke( _innerList, arguments);		
+			object returnValue = invocation.Method.Invoke( _lazyLoadedItem, arguments);		
 
 			if (_logger.IsDebugEnabled) 
 			{

Modified: ibatis/trunk/cs/mapper/IBatisNet.DataMapper/Proxy/LazyLoadProxyFactory.cs
URL: http://svn.apache.org/viewvc/ibatis/trunk/cs/mapper/IBatisNet.DataMapper/Proxy/LazyLoadProxyFactory.cs?view=diff&rev=492753&r1=492752&r2=492753
==============================================================================
--- ibatis/trunk/cs/mapper/IBatisNet.DataMapper/Proxy/LazyLoadProxyFactory.cs (original)
+++ ibatis/trunk/cs/mapper/IBatisNet.DataMapper/Proxy/LazyLoadProxyFactory.cs Thu Jan  4 13:28:10 2007
@@ -24,13 +24,11 @@
 #endregion
 
 using System;
-using System.Collections;
 using System.Reflection;
 using Castle.DynamicProxy;
 using IBatisNet.Common.Logging;
 using IBatisNet.Common.Utilities.Objects.Members;
 using IBatisNet.Common.Utilities.Proxy;
-using IBatisNet.DataMapper.Exceptions;
 using IBatisNet.DataMapper.MappedStatements;
 
 namespace IBatisNet.DataMapper.Proxy
@@ -38,21 +36,12 @@
 	/// <summary>
     /// This class is responsible of create lazy load proxies for a concrete class with virtual method.
 	/// </summary>
-	public class LazyLoadProxyFactory :ILazyFactory
+	public class LazyLoadProxyFactory : ILazyFactory
 	{
 		#region Fields
 		private static readonly ILog _logger = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType );
 		#endregion
 
-		#region Constructor
-		/// <summary>
-		/// constructor
-		/// </summary>
-		public LazyLoadProxyFactory()
-		{
-		}
-		#endregion
-
         #region ILazyFactory Members
         /// <summary>
 		/// Builds the specified lazy load proxy for a concrete class with virtual method.
@@ -65,94 +54,27 @@
         public object CreateProxy(IMappedStatement selectStatement, object param, 
 			object target, ISetAccessor setAccessor)
 		{
-			object proxy = null;
 			Type typeProxified = setAccessor.MemberType;
 
-            //bool isIList = typeof(IList).IsAssignableFrom(setAccessor.MemberType) || setAccessor.MemberType.IsSubclassOf(typeof(IList));
-            //Type returnedTypeByStatement = LazyLoadProxyFactory.GetTypeReturnedByStatemet(selectStatement, isIList); 
-	
-            ////Test if the result of the lazy load is assigable to property, test now load time instead
-            ////wait to error when the method of proxy are called
-            //if (typeProxified.IsAssignableFrom(returnedTypeByStatement) == false)
-            //{
-            //    throw new DataMapperException("Error building LazyLoad proxy for " + target.GetType() + "." + setAccessor.Name + " can not assing " + typeProxified + " to " + returnedTypeByStatement);
-            //}
+            if (_logger.IsDebugEnabled)
+            {
+                _logger.Debug(string.Format("Statement '{0}', create proxy for member {1}.", selectStatement.Id, setAccessor.MemberType));
+            }
 
-            ////Build the proxy
+            // Build the proxy
             IInterceptor handler = new LazyLoadInterceptor(selectStatement, param, target, setAccessor);
-            //if (isIList)
-            //{
-            //    if (_logger.IsDebugEnabled) 
-            //    {
-            //        _logger.Debug(string.Format("Statement '{0}', create list proxy for member {1}.", selectStatement.Id, setAccessor.MemberType));
-            //    }
-
-            //    if (selectStatement.Statement.ListClass == null)
-            //    {
-            //         proxy = ProxyGeneratorFactory.GetProxyGenerator().CreateProxy(typeof(IList), handler, new ArrayList());
-            //    }
-            //    else
-            //    {
-                    // if you want to proxy concrete classes, there are also two requirements: 
-                    // the class can not be sealed and only virtual methods can be intercepted. 
-                    // The reason is that DynamicProxy will create a subclass of your class overriding all methods 
-                    // so it can dispatch the invocations to the interceptor.
-                    proxy = ProxyGeneratorFactory.GetProxyGenerator().CreateClassProxy(typeProxified, handler, Type.EmptyTypes);
-            //    }	
-            //}
-            //else
-            //{
-            //    throw new DataMapperException(string.Format("Only proxy on IList type are supported, the member type ({0}) cannot be proxyfied.", typeProxified) ); 
-            //}
 
+            // if you want to proxy concrete classes, there are also 2 main requirements : 
+            // the class can not be sealed and only virtual methods can be intercepted. 
+            // The reason is that DynamicProxy will create a subclass of your class overriding all methods 
+            // so it can dispatch the invocations to the interceptor.
+
+            // The proxified type must also have an empty constructor
+            object proxy = ProxyGeneratorFactory.GetProxyGenerator().CreateClassProxy(typeProxified, handler, Type.EmptyTypes);
+                    
 			return proxy;
         }
 
         #endregion
-        
-        /// <summary>
-		/// Gets the type returned by statemet.
-		/// </summary>
-		/// <param name="mappedStatement">The mapped statement.</param>
-		/// <param name="isIList">if set to <c>true</c> [is Ilist].</param>
-		/// <returns>The type object return by the statement.</returns>
-		private static Type GetTypeReturnedByStatemet(IMappedStatement mappedStatement,
-			bool isIList)
-		{
-			Type returnedType = null;
-
-			if ( isIList )
-			{
-				if (mappedStatement.Statement.ListClass != null)
-				{
-					//Strongly type collection
-					returnedType = mappedStatement.Statement.ListClass;	
-				}
-				else
-				{
-					//Generic List, IList is the return type of ExecuteQueryForList(..)
-					returnedType = typeof(IList);
-				}
-			}
-			else 
-			{
-				//Property to proxified is a simple object
-				if (mappedStatement.Statement.ResultClass != null)
-				{
-					returnedType = mappedStatement.Statement.ResultClass; 
-				}
-				else if (mappedStatement.Statement.ParameterMap != null)
-				{
-					returnedType = mappedStatement.Statement.ParameterMap.Class;
-				}
-				else
-				{
-					throw new DataMapperException("We must never get here !");
-				}
-			}
-		
-			return returnedType;
-		}
-
     }
 }