When QueryForList is called and there are no results an empty IList class is 
returned. I think the same thing should happen when QueryForDataTable is called 
and there aren't any results. An IList holds a list of items. A DataTable holds 
a list of DataRows. QueryForDictionary always returns a non-null object too. 
The convention when returning "container" classes in .NET is that they're 
non-null and that the caller checks the appropriate Count property to see if 
there are any items.

If reader.Read() returns false the reader may still contain information about 
the structure of the query (it does on SqlServer ). Perhaps the code for 
initializing the DataTable can be refactored such that the Columns of the 
DataTable are still created even if the there isn't any data. This would be 
consistent with running a database query with "WHERE 1=0" ...you still get a 
resultset and column information back even though the query didn't return any 
rows. I'm pretty sure this is the behavior of SqlDataAdapter.Fill(DataTable). 
To accomplish this, the code in DataTableStrategy:

 // DataTableStrategy.Process
 dataTable = new DataTable(resultMap.Id);
 if (resultMap is AutoResultMap)
 {
  // snip - create columns calling GetSchemaTable
 }
 else
 {
  // snip - create columns from resultMap
 }

would need moved into MappedStatement.RunQueryForDataTable so a DataTable 
instance is passed to resultStrategy.Process:

 // MappedStatment.RunQueryForDataTable
 dataTable = new DataTable(resultMap.Id);
 if (resultMap is AutoResultMap)
 {
  // snip - create columns calling GetSchemaTable
 }
 else
 {
  // snip - create columns from resultMap
 }

 while (reader.Read())
 {
  dataTable = (DataTable)resultStrategy.Process(request, ref reader, dataTable);
 }

That would also be consistent with QueryForList and QueryForDictionary because 
the List<> and Dictionary<> objects are created in MappedStatement.

Going back to DataTableStrategy...when I was writing my DataSetDataMapper I 
discovered that I didn't have to write my own DataTableStrategy; I just relied 
on the fact that the resultStrategy object passed in automatically returned 
items as object[] which is what the DataRow can use to populate itself:

 DataRow dataRow = dataTable.NewRow();
 object result = resultStrategy.Process(request, ref reader, null); // 
ObjectStrategy
 if (result is object[])
 {
  dataRow.ItemArray = (object[])result;
 }
 else
 {
  dataRow[0] = result; // seems to work ok!
 }
 dataTable.Rows.Add(dataRow);

It almost seems like DataTableResultStrategy should be renamed 
"DataRowResultStrategy" because its primary focus is on populating a single 
DataRow. We're wanting to convert every row in reader into a DataRow;

 // MappedStatment.RunQueryForDataTable
 dataTable = new DataTable(resultMap.Id);
 if (resultMap is AutoResultMap)
 {
  // snip - create columns calling GetSchemaTable
 }
 else
 {
  // snip - create columns from resultMap
 }

 while (reader.Read())
 {
  DataRow dataRow = dataTable.NewRow();
  dataRow = (DataRow)dataRowResultStrategy.Process(request, ref reader, 
dataRow);
  dataTable.Rows.Add(dataRow);
 }

That's very similiar to what MappedStatement.RunQueryForList is doing. 
RunQueryForList uses the resultStrategy to convert the reader into an object 
then adds it to the list.

I hope you don't mind me commenting so much on all the commits ;-)

----- Original Message ----
From: "[EMAIL PROTECTED]" <[EMAIL PROTECTED]>
To: [EMAIL PROTECTED]
Sent: Wednesday, June 11, 2008 2:40:14 PM
Subject: svn commit: r666779 - in /ibatis/trunk/cs/V3/src: 
Apache.Ibatis.Common/Utilities/TypesResolver/ 
Apache.Ibatis.DataMapper.SqlClient.Test.2005/Fixtures/Mapping/ 
Apache.Ibatis.DataMapper.SqlClient.Test.2005/Maps/ Apache.Ibatis.DataMapper/ 
Apache.Ibatis.Da...

Author: gbayon
Date: Wed Jun 11 11:40:13 2008
New Revision: 666779

URL: http://svn.apache.org/viewvc?rev=666779&view=rev
Log:
Fix IBATISNET-272

Added:
    
ibatis/trunk/cs/V3/src/Apache.Ibatis.DataMapper/MappedStatements/ResultStrategy/DataTableStrategy.cs
   (with props)
Modified:
    
ibatis/trunk/cs/V3/src/Apache.Ibatis.Common/Utilities/TypesResolver/TypeRegistry.cs
    
ibatis/trunk/cs/V3/src/Apache.Ibatis.DataMapper.SqlClient.Test.2005/Fixtures/Mapping/StatementTest.cs
    
ibatis/trunk/cs/V3/src/Apache.Ibatis.DataMapper.SqlClient.Test.2005/Maps/Account.xml
    
ibatis/trunk/cs/V3/src/Apache.Ibatis.DataMapper/Apache.Ibatis.DataMapper.20005.csproj
    ibatis/trunk/cs/V3/src/Apache.Ibatis.DataMapper/DataMapper.cs
    ibatis/trunk/cs/V3/src/Apache.Ibatis.DataMapper/IDataMapper.cs
    
ibatis/trunk/cs/V3/src/Apache.Ibatis.DataMapper/MappedStatements/CachingStatement.cs
    
ibatis/trunk/cs/V3/src/Apache.Ibatis.DataMapper/MappedStatements/IMappedStatement.cs
    
ibatis/trunk/cs/V3/src/Apache.Ibatis.DataMapper/MappedStatements/MappedStatement.cs
    
ibatis/trunk/cs/V3/src/Apache.Ibatis.DataMapper/MappedStatements/ResultStrategy/MapStrategy.cs
    
ibatis/trunk/cs/V3/src/Apache.Ibatis.DataMapper/MappedStatements/ResultStrategy/ResultClassStrategy.cs
    
ibatis/trunk/cs/V3/src/Apache.Ibatis.DataMapper/Model/ResultMapping/ResultProperty.cs
    
ibatis/trunk/cs/V3/src/Apache.Ibatis.DataMapper/TypeHandlers/TypeHandlerFactory.cs

[snip]

Reply via email to