[ http://issues.apache.org/jira/browse/IBATISNET-98?page=comments#action_12322996 ]
Ron Grabowski commented on IBATISNET-98: ---------------------------------------- Gilles fixed this in 225374. > 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