Bug #7345 MySqlAdapter.Fill method throws Error message : Non-negative number required
Submitted: 16 Dec 2004 8:39 Modified: 16 Dec 2004 18:29
Reporter: Alessandro Zifiglio Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / NET Severity:S1 (Critical)
Version:1.0.3 gamma OS:Windows (Windows 2000)
Assigned to: Reggie Burnett CPU Architecture:Any

[16 Dec 2004 8:39] Alessandro Zifiglio
Description:
When i try to fill a dataset via the MySqlAdapter.fill method it simply hangs. Trying to explicitly throw the error and outputing the error message and stack trace, I get the following : 

Non-negative number required.\r\nParameter name: countstack trace :    at System.IO.BufferedStream.Read(Byte[] array, Int32 offset, Int32 count)\r\n   at MySql.Data.MySqlClient.PacketReader.Read(Byte[]& buffer, Int64 pos, Int64 len) in d:\\program files\\mysql\\mysql connector net 1.0.3\\src\\mysqlclient\\packetreader.cs:line 224\r\n   at MySql.Data.MySqlClient.PacketReader.ReadString(Int64 length) in d:\\program files\\mysql\\mysql connector net 1.0.3\\src\\mysqlclient\\packetreader.cs:line 297\r\n   at MySql.Data.Types.MySqlInt64.ReadValue(PacketReader reader, Int64 length) in D:\\Program Files\\MySQL\\MySQL Connector Net 1.0.3\\src\\MySqlClient\\Types\\MySqlInt64.cs:line 74\r\n   at MySql.Data.MySqlClient.NativeDriver.ReadFieldValue(Int32 index, MySqlField field, MySqlValue valObject) in d:\\program files\\mysql\\mysql connector net 1.0.3\\src\\mysqlclient\\nativedriver.cs:line 484\r\n   at MySql.Data.MySqlClient.CommandResult.get_Item(Int32 index) in d:\\program files\\mysql\\mysql connector net 1.0.3\\src\\mysqlclient\\commandresult.cs:line 76\r\n   at MySql.Data.MySqlClient.MySqlDataReader.GetFieldType(Int32 i) in d:\\program files\\mysql\\mysql connector net 1.0.3\\src\\mysqlclient\\datareader.cs:line 350\r\n   at System.Data.Common.SchemaMapping.SetupSchemaWithoutKeyInfo(MissingMappingAction mappingAction, MissingSchemaAction schemaAction, Boolean gettingData, DataColumn parentChapterColumn, Object chapterValue)\r\n   at System.Data.Common.SchemaMapping.SetupSchema(SchemaType schemaType, String sourceTableName, Boolean gettingData, DataColumn parentChapterColumn, Object parentChapterValue)\r\n   at System.Data.Common.DbDataAdapter.FillSchemaMapping(Object data, String srcTable, IDataReader dataReader, Int32 schemaCount, DataColumn parentChapterColumn, Object parentChapterValue)\r\n   at System.Data.Common.DbDataAdapter.FillSchemaMappingTry(Object data, String srcTable, IDataReader dataReader, Int32 schemaCount, DataColumn parentChapterColumn, Object parentChapterValue)

How to repeat:
This only happens in cases when my query contains more than 1 resultset. To test you can try the following stored procedure that returns two result sets :)

CREATE PROCEDURE TestDataAdapter()
BEGIN
   SELECT 1;
   SELECT 2;
END;

Now trying to fill a dataset via the MySqlAdapter will give you this error.

private MySqlConnection GetConnection(MySqlConnection conn)
		{
			if (conn != null)
				conn.Close();
	
			string connStr = "host=localhost;database=xxxx;user id=root;password=xxxxx;port=3306";

			try 
			{
				conn = new MySqlConnection( connStr );
				conn.Open();

			}
			catch (MySqlException ex) 
			{
				MessageBox.Show( "Error connecting to the server: " + ex.Message );
			}
			return conn;
		}
		private void TestDataSet()
		{
			MySqlConnection	conn = null;
			DataSet ds = null;
			conn = GetConnection(conn);
			MySqlCommand cmd = new MySqlCommand("TestDataAdapter", conn);
			cmd.CommandType = CommandType.StoredProcedure;
			using( MySqlDataAdapter da = new MySqlDataAdapter(cmd) )
			{
				da.FillError += new FillErrorEventHandler(this.FillError);
				ds = new DataSet();
				try 
				{
					// Fill the DataSet using default values for DataTable names, etc
					da.Fill(ds);
				}
				catch (Exception e)
				{
					string s = e.Message;
					throw new Exception("ERROR IN MySqlDataAdapter.Fill method, Unable to fill dataset: " + e.Message
						+ " stack : " + e.StackTrace.ToString(),e);
				}
			}
			dataGrid1.DataSource = ds;

		}
		private void FillError(object sender, FillErrorEventArgs args)
		{
			string s = "Error message : " + args.Errors.Message +
				"stack trace : " + args.Errors.StackTrace.ToString();
			MessageBox.Show(s);
			args.Continue = true;
		}

		private void Form1_Load(object sender, System.EventArgs e)
		{
			TestDataSet();
		}

Suggested fix:
Going in debug mode and stepping through, it seems that the second result set is retrieved, and after the value 2 is retrieved it continues to read the stream and PacketReader.Read method is called with the bytesLeft variable having a value of -1 ...I have tried to fix but this is no walk in the park, and requires a thorough study of the various methods being called and what they do. My apologies if I cannot do more. 
Thanks

Alessandro Zifiglio
http://www.dotnetbox.com
[16 Dec 2004 8:43] Alessandro Zifiglio
Priority high ;pPpP
[16 Dec 2004 18:29] Reggie Burnett
Thank you for your bug report. This issue has been committed to our
source repository of that product and will be incorporated into the
next release.

If necessary, you can access the source repository and build the latest
available version, including the bugfix, yourself. More information 
about accessing the source trees is available at
    http://www.mysql.com/doc/en/Installing_source_tree.html
[16 Dec 2004 20:24] Alessandro Zifiglio
oh wow, that was quick. Thank you :)
[18 Dec 2004 8:59] Alessandro Zifiglio
Reggie, 
I have cloned http://mysql.bkbits.net/connector-net connector-net and built and tried to end up having the same error. Checking the "changes" text file in the connector-net folder, all i see is : 
Bug #7243 calling prepare causing exception [fixed]
Fixed another small problem with prepared statements
Bug #7258  	MySqlCommand.Connection returns an 

So, i'm assuming that there is no fix as of yet for this bug, unless I missed something, can you confirm ;-?

Thanks :)