[ http://issues.apache.org/jira/browse/IBATISNET-98?page=all ]
     
Ron Grabowski closed IBATISNET-98:
----------------------------------


> Change implementation of IBatisNet.DataMapper.MappedStatements.RunQueryForMap 
> so it works directly with the IDataReader and has support for 
> DictionaryRowDelegate
> -----------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>          Key: IBATISNET-98
>          URL: http://issues.apache.org/jira/browse/IBATISNET-98
>      Project: iBatis for .NET
>         Type: Improvement
>     Versions: DataMapper 1.2.1
>     Reporter: Ron Grabowski
>     Assignee: Ron Grabowski
>     Priority: Minor

>
> RunQueryForObject and RunQueryForList interact directly with an IDataReader 
> object to populate the result object. RunQueryForMap does not. The current 
> implementation calls ExecuteQueryForList then iterates through the returned 
> IList to add the items to IDictionary object. The call to ExecuteQueryForList 
> also involves calculating a cache key if caching is enabled. This is 
> unnecessary becuase by the time RunQueryFor* methods are called, the check 
> for the cache should have already taken place. At the very least the current 
> implementation should call RunQueryForList internally to avoid the duplicate 
> cache key calculation. 
> A better implementation would be something similiar to the other RunQueryFor* 
> methods:
>  private IDictionary RunQueryForMap(SNIP)
>  {
>   IDictionary map = new Hashtable();                  
>   using (IDbCommand command = _preparedCommand.Create(SNIP))
>   {
>    using (IDataReader reader = command.ExecuteReader())
>    {                  
>     while (reader.Read())
>     {
>      object obj = ApplyResultMap(request, reader, null);
>      object key = ObjectProbe.GetPropertyValue(obj, keyProperty);
>      object value = obj;
>      if (valueProperty != null) 
>      {
>       value = ObjectProbe.GetPropertyValue(obj, valueProperty);
>      }
>      map.Add(key, value);
>     }
>    }
>   }
>   return map;
>  }
> That code only makes one iteration through the result set rather than placing 
> everything into an IList then re-iterating through the IList.
> The above implementation could be improved to support a delegate to control 
> how items are added to the IDictionary:
>  // warning: changing name may break existing code...
>  public delegate void ListRowDelegate(object item, IList list);
>  // new!
>  public delegate void DictionaryRowDelegate(object key, object value, 
> IDictionary dictionary);
>  ---
>  // based off of RunQueryForList (this code works...I'm using it now)
>  private IDictionary RunQueryForMap(SNIP)
>  {
>   IDictionary map = new Hashtable();                  
>   using (IDbCommand command = _preparedCommand.Create(SNIP))
>   {
>    using (IDataReader reader = command.ExecuteReader())
>    {
>     if (dictionaryRowDelegate != null)
>     {                 
>      while (reader.Read() )
>      {
>       object obj = ApplyResultMap(request, reader, null);
>       object key = ObjectProbe.GetPropertyValue(obj, keyProperty);
>       object value = obj;
>       if (valueProperty != null) 
>       {
>        value = ObjectProbe.GetPropertyValue(obj, valueProperty);
>       }
>       map.Add(key, value);
>      }
>      else
>      {
>       while (reader.Read())
>       {
>        object obj = ApplyResultMap(request, reader, null);
>        object key = ObjectProbe.GetPropertyValue(obj, keyProperty);
>        object value = obj;
>        if (valueProperty != null) 
>        {
>         value = ObjectProbe.GetPropertyValue(obj, valueProperty);
>        }
>        dictionaryRowDelegate(key, value, map);
>       }
>      }
>     }
>    }
>   }
>  return map;
>  } 
> The new implementation should mimic ExecuteQueryForRowDelegate (i.e. bypass 
> the cache for the time being). Fixing IBATISNET-87 should also fix the 
> "broken" ExecuteQueryForDictionaryRowDelegate.
> Assuming we had a result set that contained the following data:
>  UserId, PhoneNumber
>  1, 555-1212
>  1, 555-1414
>  1, 214-4757
>  2, 555-7894
>  3, 564-8975
> One could write a DictionaryRowDelegate that would associate user ids to 
> phone numbers (i.e. a simple "groupBy"):
>  private void userIdToPhoneNumbersDelegate(object key, object value, 
> IDictionary dictionary)
>  {
>   int userId = (int)key;
>   string phoneNumber = (string)value;
>   ArrayList phoneNumbers = dictionary[userId] as ArrayList;
>   if (phoneNumbers == null)
>   {
>    phoneNumbers = new ArrayList();
>   }
>   phoneNumbers.Add(phoneNumber);
>   dictionary[userId] = phoneNumbers;
>  }
> Output:
>  ((IList)temp[1]).Count == 3
>  ((IList)temp[2]).Count == 1
>  ((IList)temp[3]).Count == 1

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira

Reply via email to