Clover.NET coverage report - Coverage

Coverage timestamp: Friday, May 20, 2005 9:17:00 PM

File Stats: LOC: 1246   Methods: 39
NCLOC: 807 Classes: 3
 
Source File Conditionals Statements Methods TOTAL
MappedStatements\MappedStatement.cs 74.7 % 85.0 % 92.3 % 82.5 %
coverage coverage
1  
2   #region Apache Notice
3   /*****************************************************************************
4   * $Header: $
5   * $Revision: $
6   * $Date: $
7   *
8   * iBATIS.NET Data Mapper
9   * Copyright (C) 2004 - Gilles Bayon
10   *
11   *
12   * Licensed under the Apache License, Version 2.0 (the "License");
13   * you may not use this file except in compliance with the License.
14   * You may obtain a copy of the License at
15   *
16   * http://www.apache.org/licenses/LICENSE-2.0
17   *
18   * Unless required by applicable law or agreed to in writing, software
19   * distributed under the License is distributed on an "AS IS" BASIS,
20   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21   * See the License for the specific language governing permissions and
22   * limitations under the License.
23   *
24   ********************************************************************************/
25   #endregion
26  
27   #region Imports
28   using System;
29   using System.Data;
30   using System.Collections;
31   using System.Text;
32   using System.Reflection;
33  
34   using IBatisNet.Common;
35   using IBatisNet.Common.Utilities;
36   using IBatisNet.Common.Utilities.Objects;
37  
38   using IBatisNet.DataMapper;
39   using IBatisNet.DataMapper.Commands;
40   using IBatisNet.DataMapper.Configuration;
41   using IBatisNet.DataMapper.Configuration.Statements;
42   using IBatisNet.DataMapper.Configuration.ResultMapping;
43   using IBatisNet.DataMapper.Configuration.ParameterMapping;
44   using IBatisNet.DataMapper.Configuration.Sql.SimpleDynamic;
45   using IBatisNet.DataMapper.Configuration.Sql.Static;
46   using IBatisNet.DataMapper.TypeHandlers;
47   using IBatisNet.DataMapper.Exceptions;
48   using IBatisNet.DataMapper.Scope;
49  
50   using log4net;
51   #endregion
52  
53   namespace IBatisNet.DataMapper.MappedStatements
54   {
55  
56   /// <summary>
57   /// Summary description for MappedStatement.
58   /// </summary>
59   public class MappedStatement : IMappedStatement
60   {
61   /// <summary>
62   ///
63   /// </summary>
64   public event ExecuteEventHandler Execute;
65  
66   /// <summary>
67   /// Enumeration of the ExecuteQuery method.
68   /// </summary>
69   private enum ExecuteMethod : int
70   {
71   ExecuteQueryForObject =0,
72   ExecuteQueryForIList,
73   ExecuteQueryForArrayList,
74   ExecuteQueryForStrongTypedIList
75   }
76  
77  
78   /// <summary>
79   /// All data tor retrieve 'select' result property
80   /// </summary>
81   /// <remarks>
82   /// As ADO.NET allows to open DataReader per connection at once, we keep
83   /// all th data to make the open the 'whish' DataReader after having closed the current.
84   /// </remarks>
85   private class PostBindind
86   {
87   #region Fields
88   private MappedStatement _statement = null;
89   private ResultProperty _property = null;
90   private object _target = null;
91   private object _keys = null;
92   private ExecuteMethod _method = ExecuteMethod.ExecuteQueryForIList;
93   #endregion
94  
95   #region Properties
96   /// <summary>
97   ///
98   /// </summary>
99   public MappedStatement Statement
100   {
101 22 set { _statement = value; }
102 9 get { return _statement; }
103   }
104  
105   /// <summary>
106   ///
107   /// </summary>
108   public ResultProperty ResultProperty
109   {
110 22 set { _property = value; }
111 10 get { return _property; }
112   }
113  
114   /// <summary>
115   ///
116   /// </summary>
117   public object Target
118   {
119 22 set { _target = value; }
120 9 get { return _target; }
121   }
122  
123  
124   /// <summary>
125   ///
126   /// </summary>
127   public object Keys
128   {
129 22 set { _keys = value; }
130 9 get { return _keys; }
131   }
132  
133   /// <summary>
134   ///
135   /// </summary>
136   public ExecuteMethod Method
137   {
138 9 set { _method = value; }
139 32 get { return _method; }
140   }
141   #endregion
142  
143   }
144  
145  
146   #region Fields
147  
148   // Magic number used to set the the maximum number of rows returned to 'all'.
149   private const int NO_MAXIMUM_RESULTS = -1;
150   // Magic number used to set the the number of rows skipped to 'none'.
151   private const int NO_SKIPPED_RESULTS = -1;
152  
153   private static readonly ILog _logger = LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod().DeclaringType );
154  
155   private IStatement _statement = null;
156  
157   private SqlMapper _sqlMap = null;
158  
159   private IPreparedCommand _preparedCommand = null;
160  
161   #endregion
162  
163   #region Properties
164  
165   /// <summary>
166   /// The IPreparedCommand to use
167   /// </summary>
168 0 public IPreparedCommand PreparedCommand
169   {
170   get { return _preparedCommand; }
171   }
172  
173   /// <summary>
174   /// Name used to identify the MappedStatement amongst the others.
175   /// This the name of the SQL statement by default.
176   /// </summary>
177   public string Name
178   {
179 26537 get { return _statement.Id; }
180   }
181  
182   /// <summary>
183   /// The SQL statment used by this MappedStatement
184   /// </summary>
185   public IStatement Statement
186   {
187 28861 get { return _statement; }
188   }
189  
190   /// <summary>
191   /// The SqlMap used by this MappedStatement
192   /// </summary>
193   public SqlMapper SqlMap
194   {
195 28 get { return _sqlMap; }
196   }
197   #endregion
198  
199   #region Constructor (s) / Destructor
200   /// <summary>
201   /// Constructor
202   /// </summary>
203   /// <param name="sqlMap">An SqlMap</param>
204   /// <param name="statement">An SQL statement</param>
205 26520 internal MappedStatement( SqlMapper sqlMap, IStatement statement )
206   {
207 26520 _sqlMap = sqlMap;
208 26520 _statement = statement;
209 26520 _preparedCommand = PreparedCommandFactory.GetPreparedCommand(sqlMap.UseEmbedStatementParams);
210   }
211   #endregion
212  
213   #region Methods
214   /// <summary>
215   /// Gets a percentage of successful cache hits achieved
216   /// </summary>
217   /// <returns>The percentage of hits (0-1), or -1 if cache is disabled.</returns>
218 0 public double GetDataCacheHitRatio()
219   {
220   if (_statement.CacheModel != null)
221   {
222   return _statement.CacheModel.HitRatio;
223   }
224   else
225   {
226   return -1;
227   }
228   }
229  
230  
231   /// <summary>
232   ///
233   /// </summary>
234   /// <param name="request"></param>
235   /// <param name="reader"></param>
236   /// <param name="resultMap"></param>
237   /// <param name="resultObject"></param>
238 1 private void FillObjectWithReaderAndResultMap(RequestScope request,IDataReader reader, ResultMap resultMap, object resultObject)
239   {
240   // For each Property in the ResultMap, set the property in the object
241 1 foreach(DictionaryEntry entry in resultMap.ColumnsToPropertiesMap)
242   {
243 4 ResultProperty property = (ResultProperty)entry.Value;
244 4 SetObjectProperty(request, resultMap, property, ref resultObject, reader);
245   }
246   }
247  
248   /// <summary>
249   ///
250   /// </summary>
251   /// <param name="request"></param>
252   /// <param name="reader"></param>
253   /// <param name="resultObject"></param>
254   /// <returns></returns>
255 424 private object ApplyResultMap(RequestScope request, IDataReader reader, object resultObject)
256   {
257 424 object outObject = resultObject;
258  
259   // If there's an ResultMap, use it
260 424 if (request.ResultMap != null)
261   {
262 232 ResultMap resultMap = request.GetResultMap(reader);
263  
264 232 if (outObject == null)
265   {
266 231 outObject = resultMap.CreateInstanceOfResult();
267   }
268  
269   // For each Property in the ResultMap, set the property in the object
270 232 foreach(DictionaryEntry entry in resultMap.ColumnsToPropertiesMap)
271   {
272 1226 ResultProperty property = (ResultProperty)entry.Value;
273 1226 SetObjectProperty(request, resultMap, property, ref outObject, reader);
274   }
275   }
276   else // else try to use a ResultClass
277   {
278 192 if (_statement.ResultClass != null)
279   {
280 192 if (outObject == null)
281   {
282 192 outObject = _statement.CreateInstanceOfResultClass();
283   }
284  
285   // Check if the ResultClass is a 'primitive' Type
286 192 if (_sqlMap.TypeHandlerFactory.IsSimpleType(_statement.ResultClass))
287   {
288   // Create a ResultMap
289 30 ResultMap resultMap = new ResultMap();
290  
291   // Create a ResultProperty
292 30 ResultProperty property = new ResultProperty();
293 30 property.PropertyName = "value";
294 30 property.ColumnIndex = 0;
295 30 property.TypeHandler = _sqlMap.TypeHandlerFactory.GetTypeHandler(outObject.GetType());
296  
297 30 resultMap.AddResultPropery(property);
298  
299 30 SetObjectProperty(request, request.ResultMap, property, ref outObject, reader);
300   }
301 162 else if (outObject is Hashtable)
302   {
303 30 for (int i = 0; i < reader.FieldCount; i++)
304   {
305 24 string columnName = reader.GetName(i);
306 24 ((Hashtable) outObject).Add(columnName, reader.GetValue(i));
307   }
308   }
309   else
310   {
311 156 AutoMapReader( reader, ref outObject);
312   }
313   }
314   }
315  
316 424 return outObject;
317   }
318  
319  
320   /// <summary>
321   /// Retrieve the output parameter and map them on the result object.
322   /// This routine is only use is you specified a ParameterMap and some output attribute
323   /// or if you use a store procedure with output parameter...
324   /// </summary>
325   /// <param name="request"></param>
326   /// <param name="session">The current session.</param>
327   /// <param name="result">The result object.</param>
328   /// <param name="command">The command sql.</param>
329 300 private void RetrieveOutputParameters(RequestScope request, IDalSession session, IDbCommand command, object result)
330   {
331 300 if (request.ParameterMap != null)
332   {
333 741 for(int i=0; i<request.ParameterMap.PropertiesList.Count; i++)
334   {
335 499 ParameterProperty mapping = request.ParameterMap.GetProperty(i);
336 499 if (mapping.Direction == ParameterDirection.Output ||
337   mapping.Direction == ParameterDirection.InputOutput)
338   {
339 5 string parameterName = string.Empty;
340 5 if (session.DataSource.Provider.UseParameterPrefixInParameter == false)
341   {
342 0 parameterName = mapping.ColumnName;
343   }
344   else
345   {
346 5 parameterName = session.DataSource.Provider.ParameterPrefix +
347   mapping.ColumnName;
348   }
349  
350 5 if (mapping.TypeHandler == null) // Find the TypeHandler
351   {
352 0 lock(mapping)
353   {
354   if (mapping.TypeHandler == null)
355   {
356   Type propertyType =ObjectProbe.GetPropertyTypeForGetter(result,mapping.PropertyName);
357  
358   mapping.TypeHandler = _sqlMap.TypeHandlerFactory.GetTypeHandler(propertyType);
359   }
360   }
361   }
362  
363 5 object dataBaseValue = mapping.TypeHandler.GetDataBaseValue( ((IDataParameter)command.Parameters[parameterName]).Value, result.GetType() );
364  
365 5 ObjectProbe.SetPropertyValue(result, mapping.PropertyName, dataBaseValue);
366   }
367   }
368   }
369   }
370  
371  
372   #region ExecuteForObject
373  
374   /// <summary>
375   /// Executes an SQL statement that returns a single row as an Object.
376   /// </summary>
377   /// <param name="session">The session used to execute the statement.</param>
378   /// <param name="parameterObject">The object used to set the parameters in the SQL.</param>
379   /// <returns>The object</returns>
380 140 public virtual object ExecuteQueryForObject( IDalSession session, object parameterObject )
381   {
382 140 return ExecuteQueryForObject(session, parameterObject, null);
383   }
384  
385  
386   /// <summary>
387   /// Executes an SQL statement that returns a single row as an Object of the type of
388   /// the resultObject passed in as a parameter.
389   /// </summary>
390   /// <param name="session">The session used to execute the statement.</param>
391   /// <param name="parameterObject">The object used to set the parameters in the SQL.</param>
392   /// <param name="resultObject">The result object.</param>
393   /// <returns>The object</returns>
394 141 public virtual object ExecuteQueryForObject(IDalSession session, object parameterObject, object resultObject )
395   {
396 141 object obj = null;
397 141 RequestScope request = _statement.Sql.GetRequestScope(parameterObject, session);;
398  
399 141 if (_statement.CacheModel == null)
400   {
401 140 obj = RunQueryForObject(request, session, parameterObject, resultObject);
402   }
403   else
404   {
405 1 CacheKey key = null;
406 1 if (_statement.ParameterMap != null)
407   {
408 1 key = new CacheKey(_sqlMap.TypeHandlerFactory, this.Name,
409   request.PreparedStatement.PreparedSql,
410   parameterObject,
411   request.ParameterMap.GetPropertyNameArray(),
412   NO_SKIPPED_RESULTS,
413   NO_MAXIMUM_RESULTS,
414   CacheKeyType.Object);
415   }
416   else
417   {
418 0 key = new CacheKey(_sqlMap.TypeHandlerFactory, this.Name,
419   request.PreparedStatement.PreparedSql,
420   parameterObject,
421   new string[0],
422   NO_SKIPPED_RESULTS,
423   NO_MAXIMUM_RESULTS,
424   CacheKeyType.Object);
425   }
426  
427 1 obj = _statement.CacheModel[key];
428 1 if (obj == null)
429   {
430 1 obj = RunQueryForObject(request, session, parameterObject, resultObject);
431 1 _statement.CacheModel[key] = obj;
432   }
433   }
434  
435 141 return obj;
436   }
437  
438  
439   /// <summary>
440   /// Executes an SQL statement that returns a single row as an Object of the type of
441   /// the resultObject passed in as a parameter.
442   /// </summary>
443   /// <param name="request">The request scope.</param>
444   /// <param name="session">The session used to execute the statement.</param>
445   /// <param name="parameterObject">The object used to set the parameters in the SQL.</param>
446   /// <param name="resultObject">The result object.</param>
447   /// <returns>The object</returns>
448 141 private object RunQueryForObject(RequestScope request, IDalSession session, object parameterObject, object resultObject )
449   {
450 141 object result = resultObject;
451  
452   //using ( IDbCommand command = CreatePreparedCommand(request, session, parameterObject ))
453 141 using ( IDbCommand command = _preparedCommand.Create( request, session, this.Statement, parameterObject ) )
454   {
455 141 using ( IDataReader reader = command.ExecuteReader() )
456   {
457 141 if ( reader.Read() )
458   {
459 133 result = ApplyResultMap(request, reader, resultObject);
460   }
461   }
462  
463 141 ExecutePostSelect( session, request);
464  
465   #region remark
466   // If you are using the OleDb data provider (as you are), you need to close the
467   // DataReader before output parameters are visible.
468   #endregion
469  
470 141 RetrieveOutputParameters(request, session, command, parameterObject);
471   }
472  
473 141 return result;
474   }
475  
476   #endregion
477  
478   #region ExecuteQueryForList
479  
480   /// <summary>
481   /// Runs a query with a custom object that gets a chance
482   /// to deal with each row as it is processed.
483   /// </summary>
484   /// <param name="session">The session used to execute the statement.</param>
485   /// <param name="parameterObject">The object used to set the parameters in the SQL.</param>
486   /// <param name="rowDelegate"></param>
487 1 public virtual IList ExecuteQueryForRowDelegate( IDalSession session, object parameterObject, SqlMapper.RowDelegate rowDelegate )
488   {
489 1 RequestScope request = _statement.Sql.GetRequestScope(parameterObject, session);;
490  
491 1 if (rowDelegate == null)
492   {
493 0 throw new DataMapperException("A null RowDelegate was passed to QueryForRowDelegate.");
494   }
495  
496 1 return RunQueryForList(request, session, parameterObject, NO_SKIPPED_RESULTS, NO_MAXIMUM_RESULTS, rowDelegate);
497   }
498  
499  
500   /// <summary>
501   /// Executes the SQL and retuns all rows selected. This is exactly the same as
502   /// calling ExecuteQueryForList(session, parameterObject, NO_SKIPPED_RESULTS, NO_MAXIMUM_RESULTS).
503   /// </summary>
504   /// <param name="session">The session used to execute the statement.</param>
505   /// <param name="parameterObject">The object used to set the parameters in the SQL.</param>
506   /// <returns>A List of result objects.</returns>
507 78 public virtual IList ExecuteQueryForList( IDalSession session, object parameterObject )
508   {
509 78 return ExecuteQueryForList( session, parameterObject, NO_SKIPPED_RESULTS, NO_MAXIMUM_RESULTS);
510   }
511  
512  
513   /// <summary>
514   /// Executes the SQL and retuns a subset of the rows selected.
515   /// </summary>
516   /// <param name="session">The session used to execute the statement.</param>
517   /// <param name="parameterObject">The object used to set the parameters in the SQL.</param>
518   /// <param name="skipResults">The number of rows to skip over.</param>
519   /// <param name="maxResults">The maximum number of rows to return.</param>
520   /// <returns>A List of result objects.</returns>
521 93 public virtual IList ExecuteQueryForList( IDalSession session, object parameterObject, int skipResults, int maxResults )
522   {
523 93 IList list = null;
524 93 RequestScope request = _statement.Sql.GetRequestScope(parameterObject, session);;
525  
526 93 if (_statement.CacheModel == null)
527   {
528 81 list = RunQueryForList(request, session, parameterObject, skipResults, maxResults, null);
529   }
530   else
531   {
532 12 CacheKey key = null;
533 12 if (_statement.ParameterMap != null)
534   {
535 0 key = new CacheKey(_sqlMap.TypeHandlerFactory, this.Name,
536   request.PreparedStatement.PreparedSql,
537   parameterObject,
538   request.ParameterMap.GetPropertyNameArray(),
539   skipResults,
540   maxResults,
541   CacheKeyType.List);
542   }
543   else
544   {
545 12 key = new CacheKey(_sqlMap.TypeHandlerFactory, this.Name,
546   request.PreparedStatement.PreparedSql,
547   parameterObject,
548   new string[0],
549   skipResults,
550   maxResults,
551   CacheKeyType.List);
552   }
553  
554 12 list = (IList)_statement.CacheModel[key];
555 12 if (list == null)
556   {
557 7 list = RunQueryForList(request, session, parameterObject, skipResults, maxResults, null);
558 7 _statement.CacheModel[key] = list;
559   }
560   }
561  
562 93 return list;
563   }
564  
565  
566   /// <summary>
567   /// Executes the SQL and retuns a List of result objects.
568   /// </summary>
569   /// <param name="request">The request scope.</param>
570   /// <param name="session">The session used to execute the statement.</param>
571   /// <param name="parameterObject">The object used to set the parameters in the SQL.</param>
572   /// <param name="skipResults">The number of rows to skip over.</param>
573   /// <param name="maxResults">The maximum number of rows to return.</param>
574   /// <param name="rowDelegate"></param>
575   /// <returns>A List of result objects.</returns>
576 89 private IList RunQueryForList(RequestScope request, IDalSession session, object parameterObject, int skipResults, int maxResults, SqlMapper.RowDelegate rowDelegate)
577   {
578 89 IList list = null;
579  
580   //using ( IDbCommand command = CreatePreparedCommand(request, session, parameterObject ))
581 89 using ( IDbCommand command = _preparedCommand.Create( request, session, this.Statement, parameterObject ) )
582   {
583 89 if (_statement.ListClass == null)
584   {
585 86 list = new ArrayList();
586   }
587   else
588   {
589 3 list = _statement.CreateInstanceOfListClass();
590   }
591  
592 89 using ( IDataReader reader = command.ExecuteReader() )
593   {
594   // skip results
595 116 for (int i = 0; i < skipResults; i++)
596   {
597 28 if (!reader.Read())
598   {
599 1 break;
600   }
601   }
602  
603 89 int n = 0;
604  
605 89 if (rowDelegate == null)
606   {
607 369 while ( (maxResults == NO_MAXIMUM_RESULTS || n < maxResults)
608   && reader.Read() )
609   {
610 281 object obj = ApplyResultMap(request, reader, null);
611  
612 281 list.Add( obj );
613 281 n++;
614   }
615   }
616   else
617   {
618 6 while ( (maxResults == NO_MAXIMUM_RESULTS || n < maxResults)
619   && reader.Read() )
620   {
621 5 object obj = ApplyResultMap(request, reader, null);
622  
623 5 rowDelegate(obj, list);
624 5 n++;
625   }
626   }
627   }
628  
629 89 ExecutePostSelect( session, request);
630  
631 89 RetrieveOutputParameters(request, session, command, parameterObject);
632   }
633  
634 89 return list;
635   }
636  
637  
638   /// <summary>
639   /// Executes the SQL and and fill a strongly typed collection.
640   /// </summary>
641   /// <param name="session">The session used to execute the statement.</param>
642   /// <param name="parameterObject">The object used to set the parameters in the SQL.</param>
643   /// <param name="resultObject">A strongly typed collection of result objects.</param>
644 1 public virtual void ExecuteQueryForList(IDalSession session, object parameterObject, IList resultObject )
645   {
646 1 RequestScope request = _statement.Sql.GetRequestScope(parameterObject, session);;
647  
648   //using ( IDbCommand command = CreatePreparedCommand(request, session, parameterObject ) )
649 1 using ( IDbCommand command = _preparedCommand.Create( request, session, this.Statement, parameterObject ) )
650   {
651 1 using ( IDataReader reader = command.ExecuteReader() )
652   {
653 6 while ( reader.Read() )
654   {
655 5 object obj = ApplyResultMap(request, reader, null);
656  
657 5 resultObject.Add( obj );
658   }
659   }
660  
661 1 ExecutePostSelect( session, request);
662  
663 1 RetrieveOutputParameters(request, session, command, parameterObject);
664   }
665   }
666  
667  
668   #endregion
669  
670   #region ExecuteUpdate, ExecuteInsert
671  
672   /// <summary>
673   /// Execute an update statement. Also used for delete statement.
674   /// Return the number of row effected.
675   /// </summary>
676   /// <param name="session">The session used to execute the statement.</param>
677   /// <param name="parameterObject">The object used to set the parameters in the SQL.</param>
678   /// <returns>The number of row effected.</returns>
679 13 public virtual int ExecuteUpdate(IDalSession session, object parameterObject )
680   {
681 13 int rows = 0; // the number of rows affected
682 13 RequestScope request = _statement.Sql.GetRequestScope(parameterObject, session);;
683  
684   //using (IDbCommand command = CreatePreparedCommand(request, session, parameterObject ))
685 13 using ( IDbCommand command = _preparedCommand.Create( request, session, this.Statement, parameterObject ) )
686   {
687 12 rows = command.ExecuteNonQuery();
688  
689 12 ExecutePostSelect( session, request);
690  
691 12 RetrieveOutputParameters(request, session, command, parameterObject);
692   }
693  
694 12 RaiseExecuteEvent();
695  
696 12 return rows;
697   }
698  
699  
700   /// <summary>
701   /// Execute an insert statement. Fill the parameter object with
702   /// the ouput parameters if any, also could return the insert generated key
703   /// </summary>
704   /// <param name="session">The session</param>
705   /// <param name="parameterObject">The parameter object used to fill the statement.</param>
706   /// <returns>Can return the insert generated key.</returns>
707 57 public virtual object ExecuteInsert(IDalSession session, object parameterObject )
708   {
709 57 object generatedKey = null;
710 57 SelectKey selectKeyStatement = null;
711 57 RequestScope request = _statement.Sql.GetRequestScope(parameterObject, session);;
712  
713 57 if (_statement is Insert)
714   {
715 34 selectKeyStatement = ((Insert)_statement).SelectKey;
716   }
717  
718 57 if (selectKeyStatement != null && !selectKeyStatement.isAfter)
719   {
720 1 MappedStatement mappedStatement = _sqlMap.GetMappedStatement( selectKeyStatement.Id );
721 1 generatedKey = mappedStatement.ExecuteQueryForObject(session, parameterObject);
722  
723 1 ObjectProbe.SetPropertyValue(parameterObject, selectKeyStatement.PropertyName, generatedKey);
724   }
725  
726   //using (IDbCommand command = CreatePreparedCommand(request, session, parameterObject ))
727 57 using ( IDbCommand command = _preparedCommand.Create( request, session, this.Statement, parameterObject ) )
728   {
729 57 if (_statement is Insert)
730   {
731 34 command.ExecuteNonQuery();
732   }
733   else
734   {
735 23 generatedKey = command.ExecuteScalar();
736 23 if ( (_statement.ResultClass!=null) &&
737   _sqlMap.TypeHandlerFactory.IsSimpleType(_statement.ResultClass) )
738   {
739 8 ITypeHandler typeHandler = _sqlMap.TypeHandlerFactory.GetTypeHandler(_statement.ResultClass);
740 8 generatedKey = typeHandler.GetDataBaseValue(generatedKey, _statement.ResultClass);
741   }
742   }
743  
744 57 if (selectKeyStatement != null && selectKeyStatement.isAfter)
745   {
746 9 MappedStatement mappedStatement = _sqlMap.GetMappedStatement( selectKeyStatement.Id );
747 9 generatedKey = mappedStatement.ExecuteQueryForObject(session, parameterObject);
748  
749 9 ObjectProbe.SetPropertyValue(parameterObject, selectKeyStatement.PropertyName, generatedKey);
750   }
751  
752 57 ExecutePostSelect( session, request);
753  
754 57 RetrieveOutputParameters(request, session, command, parameterObject);
755   }
756  
757 57 RaiseExecuteEvent();
758  
759 57 return generatedKey;
760   }
761  
762   #endregion
763  
764   #region ExecuteQueryForMap
765  
766   /// <summary>
767   /// Executes the SQL and retuns all rows selected in a map that is keyed on the property named
768   /// in the keyProperty parameter. The value at each key will be the value of the property specified
769   /// in the valueProperty parameter. If valueProperty is null, the entire result object will be entered.
770   /// </summary>
771   /// <param name="session">
772   /// The session used to execute the statement
773   /// </param>
774   /// <param name="parameterObject">
775   /// The object used to set the parameters in the SQL.
776   /// </param>
777   /// <param name="keyProperty">
778   /// The property of the result object to be used as the key.
779   /// </param>
780   /// <param name="valueProperty">
781   /// The property of the result object to be used as the value (or null)
782   /// </param>
783   /// <returns>A hashtable of object containing the rows keyed by keyProperty.</returns>
784   ///<exception cref="DataMapperException">
785   ///If a transaction is not in progress, or the database throws an exception.
786   ///</exception>
787 3 public virtual IDictionary ExecuteQueryForMap( IDalSession session, object parameterObject, string keyProperty, string valueProperty )
788   {
789 3 IDictionary map = new Hashtable();
790 3 RequestScope request = _statement.Sql.GetRequestScope(parameterObject, session);;
791  
792 3 if (_statement.CacheModel == null)
793   {
794 3 map = RunQueryForMap(request, session, parameterObject, keyProperty, valueProperty );
795   }
796   else
797   {
798 0 CacheKey key = null;
799 0 if (_statement.ParameterMap != null)
800   {
801   key = new CacheKey(_sqlMap.TypeHandlerFactory, this.Name,
802   request.PreparedStatement.PreparedSql,
803   parameterObject,
804   request.ParameterMap.GetPropertyNameArray(),
805   NO_SKIPPED_RESULTS,
806   NO_MAXIMUM_RESULTS,
807   CacheKeyType.Map);
808   }
809   else
810   {
811   key = new CacheKey(_sqlMap.TypeHandlerFactory, this.Name,
812   request.PreparedStatement.PreparedSql,
813   parameterObject,
814   new string[0],
815   NO_SKIPPED_RESULTS,
816   NO_MAXIMUM_RESULTS,
817   CacheKeyType.Map);
818   }
819  
820 0 map = (IDictionary)_statement.CacheModel[key];
821 0 if (map == null)
822   {
823   map = RunQueryForMap( request, session, parameterObject, keyProperty, valueProperty );
824   _statement.CacheModel[key] = map;
825   }
826   }
827  
828 3 return map;
829   }
830  
831  
832   /// <summary>
833   /// Executes the SQL and retuns all rows selected in a map that is keyed on the property named
834   /// in the keyProperty parameter. The value at each key will be the value of the property specified
835   /// in the valueProperty parameter. If valueProperty is null, the entire result object will be entered.
836   /// </summary>
837   /// <param name="request">The request scope.</param>
838   /// <param name="session">The session used to execute the statement</param>
839   /// <param name="parameterObject">The object used to set the parameters in the SQL.</param>
840   /// <param name="keyProperty">The property of the result object to be used as the key.</param>
841   /// <param name="valueProperty">The property of the result object to be used as the value (or null)</param>
842   /// <returns>A hashtable of object containing the rows keyed by keyProperty.</returns>
843   ///<exception cref="DataMapperException">If a transaction is not in progress, or the database throws an exception.</exception>
844 3 private IDictionary RunQueryForMap( RequestScope request, IDalSession session,
845   object parameterObject, string keyProperty, string valueProperty )
846   {
847 3 IDictionary map = new Hashtable();
848  
849 3 IList list = ExecuteQueryForList(session, parameterObject);
850  
851 23 for(int i =0; i<list.Count; i++)
852   {
853 20 object obj = list[i];
854 20 if (obj != null)
855   {
856 20 object key = ObjectProbe.GetPropertyValue(obj, keyProperty);
857  
858 20 object value = obj;
859 20 if (valueProperty != null)
860   {
861 5 value = ObjectProbe.GetPropertyValue(obj, valueProperty);
862   }
863 20 map.Add(key, value);
864   }
865   }
866  
867 3 return map;
868   }
869  
870  
871   #endregion
872  
873   /// <summary>
874   /// Process 'select' result properties
875   /// </summary>
876   /// <param name="request"></param>
877   /// <param name="session"></param>
878 300 private void ExecutePostSelect(IDalSession session, RequestScope request)
879   {
880 309 while (request.QueueSelect.Count>0)
881   {
882 9 PostBindind postSelect = request.QueueSelect.Dequeue() as PostBindind;
883  
884 9 if (postSelect.Method == ExecuteMethod.ExecuteQueryForIList)
885   {
886 3 object values = postSelect.Statement.ExecuteQueryForList(session, postSelect.Keys);
887 3 ObjectProbe.SetPropertyValue( postSelect.Target, postSelect.ResultProperty.PropertyName, values);
888   }
889 6 else if (postSelect.Method == ExecuteMethod.ExecuteQueryForStrongTypedIList)
890   {
891 0 object values = Activator.CreateInstance(postSelect.ResultProperty.PropertyInfo.PropertyType);
892 0 postSelect.Statement.ExecuteQueryForList(session, postSelect.Keys, (IList)values);
893 0 ObjectProbe.SetPropertyValue( postSelect.Target, postSelect.ResultProperty.PropertyName, values);
894   }
895 9 if (postSelect.Method == ExecuteMethod.ExecuteQueryForArrayList)
896   {
897 1 IList values = postSelect.Statement.ExecuteQueryForList(session, postSelect.Keys);
898 1 Type elementType = postSelect.ResultProperty.PropertyInfo.PropertyType.GetElementType();
899  
900 1 Array array = Array.CreateInstance(elementType, values.Count);
901 3 for(int i=0;i<values.Count;i++)
902   {
903 2 array.SetValue(values[i],i);
904   }
905  
906 1 postSelect.ResultProperty.PropertyInfo.SetValue(postSelect.Target, array, null);
907   }
908 8 else if (postSelect.Method == ExecuteMethod.ExecuteQueryForObject)
909   {
910 5 object value = postSelect.Statement.ExecuteQueryForObject(session, postSelect.Keys);
911 5 ObjectProbe.SetPropertyValue( postSelect.Target, postSelect.ResultProperty.PropertyName, value);
912   }
913   }
914   }
915  
916  
917   /// <summary>
918   ///
919   /// </summary>
920   /// <param name="request"></param>
921   /// <param name="resultMap"></param>
922   /// <param name="mapping"></param>
923   /// <param name="target"></param>
924   /// <param name="reader"></param>
925 1260 private void SetObjectProperty(RequestScope request, ResultMap resultMap,
926   ResultProperty mapping, ref object target, IDataReader reader)
927   {
928 1260 string selectStatement = mapping.Select;
929  
930 1260 if (selectStatement.Length == 0 && mapping.NestedResultMap == null)
931   {
932   // If the property is not a 'select' ResultProperty
933   // or a 'resultMap' ResultProperty
934   // We have a 'normal' ResultMap
935  
936   #region Not a select statement
937 1237 if (mapping.TypeHandler == null) // Find the TypeHandler
938   {
939 0 lock(mapping)
940   {
941   if (mapping.TypeHandler == null)
942   {
943   int columnIndex = 0;
944   if (mapping.ColumnIndex == ResultProperty.UNKNOWN_COLUMN_INDEX)
945   {
946   columnIndex = reader.GetOrdinal(mapping.ColumnName);
947   }
948   else
949   {
950   columnIndex = mapping.ColumnIndex;
951   }
952   Type systemType =((IDataRecord)reader).GetFieldType(columnIndex);
953  
954   mapping.TypeHandler = _sqlMap.TypeHandlerFactory.GetTypeHandler(systemType);
955   }
956   }
957   }
958  
959 1237 object dataBaseValue = mapping.GetDataBaseValue( reader );
960  
961 1237 if (resultMap != null)
962   {
963 1207 resultMap.SetValueOfProperty( ref target, mapping, dataBaseValue );
964   }
965   else
966   {
967 30 MappedStatement.SetValueOfProperty( ref target, mapping, dataBaseValue );
968   }
969   #endregion
970   }
971 23 else if (mapping.NestedResultMap != null) // 'resultMap' ResultProperty
972   {
973 1 object obj = null;
974  
975 1 obj = mapping.NestedResultMap.CreateInstanceOfResult();
976 1 FillObjectWithReaderAndResultMap(request, reader, mapping.NestedResultMap, obj);
977 1 MappedStatement.SetValueOfProperty( ref target, mapping, obj );
978   }
979   else //'select' ResultProperty
980   {
981   // Get the select statement
982 22 MappedStatement queryStatement = _sqlMap.GetMappedStatement(selectStatement);
983 22 string paramString = mapping.ColumnName;
984 22 object keys = null;
985 22 bool wasNull = false;
986  
987   #region Find Key(s)
988 22 if (paramString.IndexOf(',')>0 || paramString.IndexOf('=')>0) // composite parameters key
989   {
990 4 IDictionary keyMap = new Hashtable();
991 4 keys = keyMap;
992   // define which character is seperating fields
993 4 char[] splitter = {'=',','};
994  
995 4 string[] paramTab = paramString.Split(splitter);
996 4 if (paramTab.Length % 2 != 0)
997   {
998 0 throw new DataMapperException("Invalid composite key string format in '"+mapping.PropertyName+". It must be: property1=column1,property2=column2,...");
999   }
1000 4 IEnumerator enumerator = paramTab.GetEnumerator();
1001 11 while (!wasNull && enumerator.MoveNext())
1002   {
1003 7 string hashKey = ((string)enumerator.Current).Trim();
1004 7 enumerator.MoveNext();
1005 7 object hashValue = reader.GetValue( reader.GetOrdinal(((string)enumerator.Current).Trim()) );
1006  
1007 7 keyMap.Add(hashKey, hashValue );
1008 7 wasNull = (hashValue == System.DBNull.Value);
1009   }
1010   }
1011   else // single parameter key
1012   {
1013 18 keys = reader.GetValue(reader.GetOrdinal(paramString));
1014 18 wasNull = reader.IsDBNull(reader.GetOrdinal(paramString));
1015   }
1016   #endregion
1017  
1018 22 if (wasNull)
1019   {
1020   // set the value of an object property to null
1021 0 ObjectProbe.SetPropertyValue(target, mapping.PropertyName, null);
1022   }
1023   else // Collection object or .Net object
1024   {
1025 22 PostBindind postSelect = new PostBindind();
1026 22 postSelect.Statement = queryStatement;
1027 22 postSelect.Keys = keys;
1028 22 postSelect.Target = target;
1029 22 postSelect.ResultProperty = mapping;
1030  
1031   #region Collection object or .NET object
1032   // Check if the object to Map implement 'IList' or is IList type
1033   // If yes the ResultProperty is map to a IList object
1034 22 if ( (mapping.PropertyInfo.PropertyType.GetInterface("IList") != null) ||
1035   (mapping.PropertyInfo.PropertyType == typeof(IList)))
1036   {
1037 16 object values = null;
1038  
1039 16 if (mapping.IsLazyLoad)
1040   {
1041 13 values = LazyLoadList.NewInstance(_sqlMap.DataSource, queryStatement, keys, target, mapping.PropertyName);
1042 13 ObjectProbe.SetPropertyValue( target, mapping.PropertyName, values);
1043   }
1044   else
1045   {
1046   //IDalSession session = new SqlMapSession(_sqlMap.DataSource);
1047  
1048 3 if (mapping.PropertyInfo.PropertyType == typeof(IList))
1049   {
1050 3 postSelect.Method = ExecuteMethod.ExecuteQueryForIList;
1051   }
1052   else
1053   {
1054 0 postSelect.Method = ExecuteMethod.ExecuteQueryForStrongTypedIList;
1055   }
1056   }
1057   }
1058 6 else if (mapping.PropertyInfo.PropertyType.IsArray)
1059   {
1060 1 postSelect.Method = ExecuteMethod.ExecuteQueryForArrayList;
1061   }
1062   else // The ResultProperty is map to a .Net object
1063   {
1064 5 postSelect.Method = ExecuteMethod.ExecuteQueryForObject;
1065   }
1066   #endregion
1067  
1068 22 if (!mapping.IsLazyLoad)
1069   {
1070 9 request.QueueSelect.Enqueue(postSelect);
1071   }
1072   }
1073   }
1074   }
1075  
1076  
1077 646 private static void SetValueOfProperty( ref object target, ResultProperty property, object dataBaseValue )
1078   {
1079 646 if (target is Hashtable)
1080   {
1081 0 ((Hashtable) target).Add(property.PropertyName, dataBaseValue);
1082   }
1083   else
1084   {
1085 646 if (property.PropertyName == "value")
1086   {
1087 30 target = dataBaseValue;
1088   }
1089   else
1090   {
1091 616 if (dataBaseValue == null)
1092   {
1093 38 if (property.PropertyInfo != null)
1094   {
1095 38 property.PropertyInfo.SetValue( target, null, null );
1096   }
1097   else
1098   {
1099 0 ObjectProbe.SetPropertyValue( target, property.PropertyName, null);
1100   }
1101   }
1102   else
1103   {
1104 578 if (property.PropertyInfo != null)
1105   {
1106 578 property.PropertyInfo.SetValue( target, dataBaseValue, null );
1107   }
1108   else
1109   {
1110 0 ObjectProbe.SetPropertyValue( target, property.PropertyName, dataBaseValue);
1111   }
1112   }
1113   }
1114   }
1115   }
1116  
1117  
1118   /// <summary>
1119   /// Raise an event ExecuteEventArgs
1120   /// (Used when a query is executed)
1121   /// </summary>
1122 69 private void RaiseExecuteEvent()
1123   {
1124 69 ExecuteEventArgs e = new ExecuteEventArgs();
1125 69 e.StatementName = _statement.Id;
1126 69 if (Execute != null)
1127   {
1128 5 Execute(this, e);
1129   }
1130   }
1131  
1132   /// <summary>
1133   /// ToString implementation.
1134   /// </summary>
1135   /// <returns>A string that describes the MappedStatement</returns>
1136 0 public override string ToString()
1137   {
1138   StringBuilder buffer = new StringBuilder();
1139   buffer.Append("\tMappedStatement: " + this.Name + "\n");
1140   if (_statement.ParameterMap != null) buffer.Append(_statement.ParameterMap.Id);
1141   if (_statement.ResultMap != null) buffer.Append(_statement.ResultMap.Id);
1142  
1143   return buffer.ToString();
1144   }
1145  
1146  
1147   private ReaderAutoMapper _readerAutoMapper = null;
1148  
1149 156 private void AutoMapReader( IDataReader reader,ref object resultObject)
1150   {
1151 156 if (_readerAutoMapper == null)
1152   {
1153 69 lock (this)
1154   {
1155 69 if (_readerAutoMapper == null)
1156   {
1157 69 _readerAutoMapper = new ReaderAutoMapper(_sqlMap.TypeHandlerFactory, reader, ref resultObject);
1158   }
1159   }
1160   }
1161  
1162 156 _readerAutoMapper.AutoMapReader( reader, ref resultObject );
1163   }
1164   #endregion
1165  
1166   private class ReaderAutoMapper
1167   {
1168  
1169   // private IList _mappings = new ArrayList();
1170   private ResultMap _resultMap = new ResultMap();
1171  
1172   /// <summary>
1173   ///
1174   /// </summary>
1175   /// <param name="reader"></param>
1176   /// <param name="resultObject"></param>
1177   /// <param name="typeHandlerFactory"></param>
1178 69 public ReaderAutoMapper(TypeHandlerFactory typeHandlerFactory, IDataReader reader,ref object resultObject)
1179   {
1180 69 try
1181   {
1182   // Get all PropertyInfo from the resultObject properties
1183 69 ReflectionInfo reflectionInfo = ReflectionInfo.GetInstance(resultObject.GetType());
1184 69 string[] propertiesName = reflectionInfo.GetWriteablePropertyNames();
1185  
1186 69 Hashtable propertyMap = new Hashtable();
1187 526 for (int i = 0; i < propertiesName.Length; i++)
1188   {
1189 457 propertyMap.Add( propertiesName[i].ToUpper(), reflectionInfo.GetSetter(propertiesName[i]) );
1190   }
1191  
1192   // Get all column Name from the reader
1193   // and build a resultMap from with the help of the PropertyInfo[].
1194 69 DataTable dataColumn = reader.GetSchemaTable();
1195 337 for (int i = 0; i < dataColumn.Rows.Count; i++)
1196   {
1197 268 string columnName = dataColumn.Rows[i][0].ToString();
1198 268 PropertyInfo matchedPropertyInfo = propertyMap[columnName.ToUpper()] as PropertyInfo;
1199  
1200 268 ResultProperty property = new ResultProperty();
1201 268 property.ColumnName = columnName;
1202  
1203 268 if (matchedPropertyInfo != null )
1204   {
1205 268 property.PropertyName = matchedPropertyInfo.Name;
1206 268 property.Initialize(typeHandlerFactory, matchedPropertyInfo );
1207   // _mappings.Add(property);
1208 268 _resultMap.AddResultPropery(property);
1209   }
1210 0 else if (resultObject is Hashtable)
1211   {
1212   property.PropertyName = columnName;
1213   // _mappings.Add(property);
1214   _resultMap.AddResultPropery(property);
1215   }
1216  
1217   // Set TypeHandler
1218 268 Type propertyType = reflectionInfo.GetSetterType(property.PropertyName);
1219 268 property.TypeHandler = typeHandlerFactory.GetTypeHandler( propertyType );
1220   }
1221   }
1222   catch (Exception e)
1223   {
1224 0 throw new DataMapperException("Error automapping columns. Cause: " + e);
1225   }
1226   }
1227  
1228   /// <summary>
1229   ///
1230   /// </summary>
1231   /// <param name="reader"></param>
1232   /// <param name="resultObject"></param>
1233 156 public void AutoMapReader(IDataReader reader, ref object resultObject)
1234   {
1235 156 foreach (string key in _resultMap.ColumnsToPropertiesMap.Keys)
1236   {
1237 615 ResultProperty property = (ResultProperty) _resultMap.ColumnsToPropertiesMap[key];
1238 615 MappedStatement.SetValueOfProperty( ref resultObject, property,
1239   property.GetDataBaseValue( reader ));
1240   }
1241   }
1242  
1243   }
1244   }
1245   }
1246