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
Assigned to: Gilles Bayon
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