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]