context: //
  // SqlCommandTest.cs - NUnit Test Cases for testing the
  //                          SqlCommand class
  // Author:
  //      Umadevi S (sumadevi@novell.com)
  //	Sureshkumar T (tsureshkumar@novell.com)
  //	Senganal T (tsenganal@novell.com)
  //
  // Copyright (c) 2004 Novell Inc., and the individuals listed
  // on the ChangeLog entries.
  //
  // Permission is hereby granted, free of charge, to any person obtaining
  // a copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to
  // permit persons to whom the Software is furnished to do so, subject to
  // the following conditions:
  //
  // The above copyright notice and this permission notice shall be
  // included in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  //
  
  using System;
  using System.Data;
  using System.Data.Common;
  using System.Data.SqlClient;
  #if NET_2_0
  using System.Data.Sql;
  #endif
  using System.Globalization;
  #if NET_2_0
  using System.Xml;
  #endif
  
  using NUnit.Framework;
  
  namespace MonoTests.System.Data.SqlClient
  {
  	[TestFixture]
  	[Category ("sqlserver")]
  	public class SqlCommandTest
  	{
  		SqlConnection conn;
  		SqlCommand cmd;
  		string connectionString = ConnectionManager.Singleton.ConnectionString;
  		EngineConfig engine;
  
  		static readonly decimal SMALLMONEY_MAX = 214748.3647m;
  		static readonly decimal SMALLMONEY_MIN = -214748.3648m;
  
  		[SetUp]
  		public void SetUp ()
  		{
  			engine = ConnectionManager.Singleton.Engine;
  		}
  
  		[TearDown]
  		public void TearDown ()
  		{
  			if (cmd != null) {
  				cmd.Dispose ();
  				cmd = null;
  			}
  
  			if (conn != null) {
  				conn.Close ();
  				conn = null;
  			}
  		}
  
  		[Test] // ctor (String, SqlConnection, SqlTransaction)
  		public void Constructor4 ()
  		{
  			string cmdText = "select @@version";
  
  			SqlTransaction trans = null;
  			SqlConnection connA = null;
  			SqlConnection connB = null;
  
  			// transaction from same connection
  			try {
  				connA = new SqlConnection (connectionString);
  				connA.Open ();
  
  				trans = connA.BeginTransaction ();
  				cmd = new SqlCommand (cmdText, connA, trans);
  
  				Assert.AreEqual (cmdText, cmd.CommandText, "#A1");
  				Assert.AreEqual (30, cmd.CommandTimeout, "#A2");
  				Assert.AreEqual (CommandType.Text, cmd.CommandType, "#A3");
  				Assert.AreSame (connA, cmd.Connection, "#A4");
  				Assert.IsNull (cmd.Container, "#A5");
  				Assert.IsTrue (cmd.DesignTimeVisible, "#A6");
  #if NET_2_0
  				Assert.IsNull (cmd.Notification, "#A7");
  				Assert.IsTrue (cmd.NotificationAutoEnlist, "#A8");
  #endif
  				Assert.IsNotNull (cmd.Parameters, "#A9");
  				Assert.AreEqual (0, cmd.Parameters.Count, "#A10");
  				Assert.IsNull (cmd.Site, "#A11");
  				Assert.AreSame (trans, cmd.Transaction, "#A12");
  				Assert.AreEqual (UpdateRowSource.Both, cmd.UpdatedRowSource, "#A13");
  			} finally {
  				if (trans != null)
  					trans.Dispose ();
  				if (connA != null)
  					connA.Close ();
  			}
  
  			// transaction from other connection
  			try {
  				connA = new SqlConnection (connectionString);
  				connA.Open ();
  				connB = new SqlConnection (connectionString);
  				connB.Open ();
  
  				trans = connB.BeginTransaction ();
  				cmd = new SqlCommand (cmdText, connA, trans);
  
  				Assert.AreEqual (cmdText, cmd.CommandText, "#B1");
  				Assert.AreEqual (30, cmd.CommandTimeout, "#B2");
  				Assert.AreEqual (CommandType.Text, cmd.CommandType, "#B3");
  				Assert.AreSame (connA, cmd.Connection, "#B4");
  				Assert.IsNull (cmd.Container, "#B5");
  				Assert.IsTrue (cmd.DesignTimeVisible, "#B6");
  #if NET_2_0
  				Assert.IsNull (cmd.Notification, "#B7");
  				Assert.IsTrue (cmd.NotificationAutoEnlist, "#B8");
  #endif
  				Assert.IsNotNull (cmd.Parameters, "#B9");
  				Assert.AreEqual (0, cmd.Parameters.Count, "#B10");
  				Assert.IsNull (cmd.Site, "#B11");
  				Assert.AreSame (trans, cmd.Transaction, "#B12");
  				Assert.AreEqual (UpdateRowSource.Both, cmd.UpdatedRowSource, "#B13");
  			} finally {
  				if (trans != null)
  					trans.Dispose ();
  				if (connA != null)
  					connA.Close ();
  			}
  		}
  
  		[Test] // bug #341743
  		public void Dispose_Connection_Disposed ()
  		{
  			conn = (SqlConnection) ConnectionManager.Singleton.Connection;
  			ConnectionManager.Singleton.OpenConnection ();
  
  			cmd = conn.CreateCommand ();
  			cmd.CommandText = "SELECT 'a'";
  			cmd.ExecuteNonQuery ();
  
  			conn.Dispose ();
  
  			Assert.AreSame (conn, cmd.Connection, "#1");
  			cmd.Dispose ();
  			Assert.AreSame (conn, cmd.Connection, "#2");
  		}
  
  		[Test]
  		public void ExecuteScalar ()
  		{
  			conn = new SqlConnection (connectionString);
  			cmd = new SqlCommand ("", conn);
  			cmd.CommandText = "Select count(*) from numeric_family where id<=4";
  
  			// Check the Return value for a Correct Query 
  			object result = 0;
  			conn.Open ();
  			result = cmd.ExecuteScalar ();
  			Assert.AreEqual (4, (int) result, "#A1 Query Result returned is incorrect");
  
  			cmd.CommandText = "select id , type_bit from numeric_family order by id asc";
  			result = Convert.ToInt32 (cmd.ExecuteScalar ());
  			Assert.AreEqual (1, result,
  				"#A2 ExecuteScalar Should return (1,1) the result set");
  
  			cmd.CommandText = "select id from numeric_family where id=-1";
  			result = cmd.ExecuteScalar ();
  			Assert.IsNull (result, "#A3 Null should be returned if result set is empty");
  
  			// Check SqlException is thrown for Invalid Query 
  			cmd.CommandText = "select count* from numeric_family";
  			try {
  				result = cmd.ExecuteScalar ();
  				Assert.Fail ("#B1");
  			} catch (SqlException ex) {
  				Assert.AreEqual (typeof (SqlException), ex.GetType (), "#B2");
  				Assert.AreEqual ((byte) 15, ex.Class, "#B3");
  				Assert.IsNull (ex.InnerException, "#B4");
  				Assert.IsNotNull (ex.Message, "#B5");
  				if (ClientVersion == 7) {
  					// Incorrect syntax near '*'
  					Assert.IsTrue (ex.Message.IndexOf ("'*'") != -1, "#B6: " + ex.Message);
  					Assert.AreEqual (170, ex.Number, "#B7");
  				} else {
  					// Incorrect syntax near the keyword 'from'
  					Assert.IsTrue (ex.Message.IndexOf ("'from'") != -1, "#B6: " + ex.Message);
  					Assert.AreEqual (156, ex.Number, "#B7");
  				}
  				Assert.AreEqual ((byte) 1, ex.State, "#B8");
  			}
  
  			// Parameterized stored procedure calls
  
  			int int_value = 20;
  			string string_value = "output value changed";
  			string return_value = "first column of first rowset";
  
  			cmd.CommandText =
  				"create procedure #tmp_executescalar_outparams " +
  				" (@p1 int, @p2 int out, @p3 varchar(200) out) " +
  				"as " +
  				"select '" + return_value + "' as 'col1', @p1 as 'col2' " +
  				"set @p2 = @p2 * 2 " +
  				"set @p3 = N'" + string_value + "' " +
  				"select 'second rowset' as 'col1', 2 as 'col2' " +
  				"return 1";
  
  			cmd.CommandType = CommandType.Text;
  			cmd.ExecuteNonQuery ();
  
  			cmd.CommandText = "#tmp_executescalar_outparams";
  			cmd.CommandType = CommandType.StoredProcedure;
  
  			SqlParameter p1 = new SqlParameter ();
  			p1.ParameterName = "@p1";
  			p1.Direction = ParameterDirection.Input;
  			p1.DbType = DbType.Int32;
  			p1.Value = int_value;
  			cmd.Parameters.Add (p1);
  
  			SqlParameter p2 = new SqlParameter ();
  			p2.ParameterName = "@p2";
  			p2.Direction = ParameterDirection.InputOutput;
  			p2.DbType = DbType.Int32;
  			p2.Value = int_value;
  			cmd.Parameters.Add (p2);
  
  			SqlParameter p3 = new SqlParameter ();
  			p3.ParameterName = "@p3";
  			p3.Direction = ParameterDirection.Output;
  			p3.DbType = DbType.String;
  			p3.Size = 200;
  			cmd.Parameters.Add (p3);
  
  			result = cmd.ExecuteScalar ();
  			Assert.AreEqual (return_value, result, "#C1 ExecuteScalar Should return 'first column of first rowset'");
  			Assert.AreEqual (int_value * 2, p2.Value, "#C2 ExecuteScalar should fill the parameter collection with the outputted values");
  			Assert.AreEqual (string_value, p3.Value, "#C3 ExecuteScalar should fill the parameter collection with the outputted values");
  
  			p3.Size = 0;
  			p3.Value = null;
  			try {
  				cmd.ExecuteScalar ();
  				Assert.Fail ("#D1 Query should throw System.InvalidOperationException due to size = 0 and value = null");
  			} catch (InvalidOperationException ex) {
  				// String[2]: the Size property has an invalid
  				// size of 0
  				Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#D2");
  				Assert.IsNull (ex.InnerException, "#D3");
  				Assert.IsNotNull (ex.Message, "#D4");
  			} finally {
  				conn.Close ();
  			}
  		}
  
  		[Test]
  		public void ExecuteScalar_CommandText_Empty ()
  		{
  			conn = (SqlConnection) ConnectionManager.Singleton.Connection;
  			ConnectionManager.Singleton.OpenConnection ();
  
  			cmd = conn.CreateCommand ();
  
  			try {
  				cmd.ExecuteScalar ();
  				Assert.Fail ("#A1");
  			} catch (InvalidOperationException ex) {
  				// ExecuteScalar: CommandText property
  				// has not been initialized
  				Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#A2");
  				Assert.IsNull (ex.InnerException, "#A3");
  				Assert.IsNotNull (ex.Message, "#A4");
  #if NET_2_0
  				Assert.IsTrue (ex.Message.StartsWith ("ExecuteScalar"), "#A5:" + ex.Message);
  #else
  				Assert.IsTrue (ex.Message.StartsWith ("ExecuteReader"), "#A5:" + ex.Message);
  #endif
  			}
  
  			cmd.CommandText = string.Empty;
  
  			try {
  				cmd.ExecuteScalar ();
  				Assert.Fail ("#B1");
  			} catch (InvalidOperationException ex) {
  				// ExecuteScalar: CommandText property
  				// has not been initialized
  				Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#B2");
  				Assert.IsNull (ex.InnerException, "#B3");
  				Assert.IsNotNull (ex.Message, "#B4");
  #if NET_2_0
  				Assert.IsTrue (ex.Message.StartsWith ("ExecuteScalar"), "#B5:" + ex.Message);
  #else
  				Assert.IsTrue (ex.Message.StartsWith ("ExecuteReader"), "#B5:" + ex.Message);
  #endif
  			}
  
  			cmd.CommandText = null;
  
  			try {
  				cmd.ExecuteScalar ();
  				Assert.Fail ("#C1");
  			} catch (InvalidOperationException ex) {
  				// ExecuteScalar: CommandText property
  				// has not been initialized
  				Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#C2");
  				Assert.IsNull (ex.InnerException, "#C3");
  				Assert.IsNotNull (ex.Message, "#C4");
  #if NET_2_0
  				Assert.IsTrue (ex.Message.StartsWith ("ExecuteScalar"), "#C5:" + ex.Message);
  #else
  				Assert.IsTrue (ex.Message.StartsWith ("ExecuteReader"), "#C5:" + ex.Message);
  #endif
  			}
  		}
  
  		[Test]
  		public void ExecuteScalar_Connection_PendingTransaction ()
  		{
  			conn = new SqlConnection (connectionString);
  			conn.Open ();
  
  			using (SqlTransaction trans = conn.BeginTransaction ()) {
  				cmd = new SqlCommand ("select @@version", conn);
  
  				try {
  					cmd.ExecuteScalar ();
  					Assert.Fail ("#1");
  				} catch (InvalidOperationException ex) {
  					// ExecuteScalar requires the command
  					// to have a transaction object when the
  					// connection assigned to the command is
  					// in a pending local transaction.  The
  					// Transaction property of the command
  					// has not been initialized
  					Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
  					Assert.IsNull (ex.InnerException, "#3");
  					Assert.IsNotNull (ex.Message, "#4");
  #if NET_2_0
  					Assert.IsTrue (ex.Message.IndexOf ("ExecuteScalar") != -1, "#5:" + ex.Message);
  #else
  					Assert.IsTrue (ex.Message.IndexOf ("Execute") != -1, "#5:" + ex.Message);
  #endif
  				}
  			}
  		}
  
  		[Test]
  		public void ExecuteScalar_Query_Invalid ()
  		{
  			conn = new SqlConnection (connectionString);
  			conn.Open ();
  
  			cmd = new SqlCommand ("InvalidQuery", conn);
  			try {
  				cmd.ExecuteScalar ();
  				Assert.Fail ("#1");
  			} catch (SqlException ex) {
  				// Could not find stored procedure 'InvalidQuery'
  				Assert.AreEqual (typeof (SqlException), ex.GetType (), "#2");
  				Assert.AreEqual ((byte) 16, ex.Class, "#3");
  				Assert.IsNull (ex.InnerException, "#4");
  				Assert.IsNotNull (ex.Message, "#5");
  				Assert.IsTrue (ex.Message.IndexOf ("'InvalidQuery'") != -1, "#6:" + ex.Message);
  				Assert.AreEqual (2812, ex.Number, "#7");
  				Assert.AreEqual ((byte) 62, ex.State, "#8");
  			}
  		}
  
  		[Test]
  		public void ExecuteScalar_Transaction_NotAssociated ()
  		{
  			SqlTransaction trans = null;
  			SqlConnection connA = null;
  			SqlConnection connB = null;
  
  			try {
  				connA = new SqlConnection (connectionString);
  				connA.Open ();
  
  				connB = new SqlConnection (connectionString);
  				connB.Open ();
  
  				trans = connA.BeginTransaction ();
  
  				cmd = new SqlCommand ("select @@version", connB, trans);
  
  				try {
  					cmd.ExecuteScalar ();
  					Assert.Fail ("#A1");
  				} catch (InvalidOperationException ex) {
  					// The transaction object is not associated
  					// with the connection object
  					Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#A2");
  					Assert.IsNull (ex.InnerException, "#A3");
  					Assert.IsNotNull (ex.Message, "#A4");
  				} finally {
  					cmd.Dispose ();
  				}
  
  				cmd = new SqlCommand ("select @@version", connB);
  				cmd.Transaction = trans;
  
  				try {
  					cmd.ExecuteScalar ();
  					Assert.Fail ("#B1");
  				} catch (InvalidOperationException ex) {
  					// The transaction object is not associated
  					// with the connection object
  					Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#B2");
  					Assert.IsNull (ex.InnerException, "#B3");
  					Assert.IsNotNull (ex.Message, "#B4");
  				} finally {
  					cmd.Dispose ();
  				}
  			} finally {
  				if (trans != null)
  					trans.Dispose ();
  				if (connA != null)
  					connA.Close ();
  				if (connB != null)
  					connB.Close ();
  			}
  		}
  
  		[Test]
  		public void ExecuteScalar_Transaction_Only ()
  		{
  			SqlTransaction trans = null;
  
  			conn = new SqlConnection (connectionString);
  			conn.Open ();
  			trans = conn.BeginTransaction ();
  
  			cmd = new SqlCommand ("select @@version");
  			cmd.Transaction = trans;
  
  			try {
  				cmd.ExecuteScalar ();
  				Assert.Fail ("#1");
  			} catch (InvalidOperationException ex) {
  				// ExecuteScalar: Connection property has not
  				// been initialized
  				Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
  				Assert.IsNull (ex.InnerException, "#3");
  				Assert.IsNotNull (ex.Message, "#4");
  #if NET_2_0
  				Assert.IsTrue (ex.Message.StartsWith ("ExecuteScalar:"), "#5");
  #else
  				Assert.IsTrue (ex.Message.StartsWith ("ExecuteReader:"), "#5");
  #endif
  			} finally {
  				trans.Dispose ();
  			}
  		}
  
  		[Test]
  		public void ExecuteNonQuery ()
  		{
  			conn = new SqlConnection (connectionString);
  			conn.Open ();
  
  			SqlTransaction trans = conn.BeginTransaction ();
  
  			cmd = conn.CreateCommand ();
  			cmd.Transaction = trans;
  
  			int result = 0;
  
  			try {
  				cmd.CommandText = "Select id from numeric_family where id=1";
  				result = cmd.ExecuteNonQuery ();
  				Assert.AreEqual (-1, result, "#A1");
  
  				cmd.CommandText = "Insert into numeric_family (id,type_int) values (100,200)";
  				result = cmd.ExecuteNonQuery ();
  				Assert.AreEqual (1, result, "#A2 One row shud be inserted");
  
  				cmd.CommandText = "Update numeric_family set type_int=300 where id=100";
  				result = cmd.ExecuteNonQuery ();
  				Assert.AreEqual (1, result, "#A3 One row shud be updated");
  
  				// Test Batch Commands 
  				cmd.CommandText = "Select id from numeric_family where id=1;";
  				cmd.CommandText += "update numeric_family set type_int=10 where id=1000";
  				cmd.CommandText += "update numeric_family set type_int=10 where id=100";
  				result = cmd.ExecuteNonQuery ();
  				Assert.AreEqual (1, result, "#A4 One row shud be updated");
  
  				cmd.CommandText = "Delete from numeric_family where id=100";
  				result = cmd.ExecuteNonQuery ();
  				Assert.AreEqual (1, result, "#A5 One row shud be deleted");
  			} finally {
  				trans.Dispose ();
  			}
  
  			// Parameterized stored procedure calls
  
  			int int_value = 20;
  			string string_value = "output value changed";
  
  			cmd.CommandText =
  				"create procedure #tmp_executescalar_outparams " +
  				" (@p1 int, @p2 int out, @p3 varchar(200) out) " +
  				"as " +
  				"select 'test' as 'col1', @p1 as 'col2' " +
  				"set @p2 = @p2 * 2 " +
  				"set @p3 = N'" + string_value + "' " +
  				"select 'second rowset' as 'col1', 2 as 'col2' " +
  				"return 1";
  
  			cmd.CommandType = CommandType.Text;
  			cmd.ExecuteNonQuery ();
  
  			cmd.CommandText = "#tmp_executescalar_outparams";
  			cmd.CommandType = CommandType.StoredProcedure;
  
  			SqlParameter p1 = new SqlParameter ();
  			p1.ParameterName = "@p1";
  			p1.Direction = ParameterDirection.Input;
  			p1.DbType = DbType.Int32;
  			p1.Value = int_value;
  			cmd.Parameters.Add (p1);
  
  			SqlParameter p2 = new SqlParameter ("@p2", int_value);
  			p2.Direction = ParameterDirection.InputOutput;
  			cmd.Parameters.Add (p2);
  
  			SqlParameter p3 = new SqlParameter ();
  			p3.ParameterName = "@p3";
  			p3.Direction = ParameterDirection.Output;
  			p3.DbType = DbType.String;
  			p3.Size = 200;
  			cmd.Parameters.Add (p3);
  
  			cmd.ExecuteNonQuery ();
  			Assert.AreEqual (int_value * 2, p2.Value, "#B1");
  			Assert.AreEqual (string_value, p3.Value, "#B2");
  		}
  
  		[Test]
  		public void ExecuteNonQuery_Connection_PendingTransaction ()
  		{
  			conn = new SqlConnection (connectionString);
  			conn.Open ();
  
  			using (SqlTransaction trans = conn.BeginTransaction ()) {
  				cmd = new SqlCommand ("select @@version", conn);
  
  				try {
  					cmd.ExecuteNonQuery ();
  					Assert.Fail ("#1");
  				} catch (InvalidOperationException ex) {
  					// ExecuteNonQuery requires the command
  					// to have a transaction object when the
  					// connection assigned to the command is
  					// in a pending local transaction.  The
  					// Transaction property of the command
  					// has not been initialized
  					Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
  					Assert.IsNull (ex.InnerException, "#3");
  					Assert.IsNotNull (ex.Message, "#4");
  #if NET_2_0
  					Assert.IsTrue (ex.Message.IndexOf ("ExecuteNonQuery") != -1, "#5:" + ex.Message);
  #else
  					Assert.IsTrue (ex.Message.IndexOf ("Execute") != -1, "#5:" + ex.Message);
  #endif
  				}
  			}
  		}
  
  		[Test]
  		public void ExecuteNonQuery_Query_Invalid ()
  		{
  			conn = new SqlConnection (connectionString);
  			conn.Open ();
  			cmd = new SqlCommand ("select id1 from numeric_family", conn);
  
  			try {
  				cmd.ExecuteNonQuery ();
  				Assert.Fail ("#A1");
  			} catch (SqlException ex) {
  				// Invalid column name 'id1'
  				Assert.AreEqual (typeof (SqlException), ex.GetType (), "#A2");
  				Assert.AreEqual ((byte) 16, ex.Class, "#A3");
  				Assert.IsNull (ex.InnerException, "#A4");
  				Assert.IsNotNull (ex.Message, "#A5");
  				Assert.IsTrue (ex.Message.IndexOf ("'id1'") != -1, "#A6:" + ex.Message);
  				Assert.AreEqual (207, ex.Number, "#A7");
  				if (ClientVersion == 7)
  					Assert.AreEqual ((byte) 3, ex.State, "#A8");
  				else
  					Assert.AreEqual ((byte) 1, ex.State, "#A8");
  			}
  
  			// ensure connection is not closed after error
  
  			int result;
  
  			cmd.CommandText = "INSERT INTO numeric_family (id, type_int) VALUES (6100, 200)";
  			result = cmd.ExecuteNonQuery ();
  			Assert.AreEqual (1, result, "#B1");
  
  			cmd.CommandText = "DELETE FROM numeric_family WHERE id = 6100";
  			result = cmd.ExecuteNonQuery ();
  			Assert.AreEqual (1, result, "#B1");
  		}
  
  		[Test]
  		public void ExecuteNonQuery_Transaction_NotAssociated ()
  		{
  			SqlTransaction trans = null;
  			SqlConnection connA = null;
  			SqlConnection connB = null;
  
  			try {
  				connA = new SqlConnection (connectionString);
  				connA.Open ();
  
  				connB = new SqlConnection (connectionString);
  				connB.Open ();
  
  				trans = connA.BeginTransaction ();
  
  				cmd = new SqlCommand ("select @@version", connB, trans);
  
  				try {
  					cmd.ExecuteNonQuery ();
  					Assert.Fail ("#A1");
  				} catch (InvalidOperationException ex) {
  					// The transaction object is not associated
  					// with the connection object
  					Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#A2");
  					Assert.IsNull (ex.InnerException, "#A3");
  					Assert.IsNotNull (ex.Message, "#A4");
  				} finally {
  					cmd.Dispose ();
  				}
  
  				cmd = new SqlCommand ("select @@version", connB);
  				cmd.Transaction = trans;
  
  				try {
  					cmd.ExecuteNonQuery ();
  					Assert.Fail ("#B1");
  				} catch (InvalidOperationException ex) {
  					// The transaction object is not associated
  					// with the connection object
  					Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#B2");
  					Assert.IsNull (ex.InnerException, "#B3");
  					Assert.IsNotNull (ex.Message, "#B4");
  				} finally {
  					cmd.Dispose ();
  				}
  			} finally {
  				if (trans != null)
  					trans.Dispose ();
  				if (connA != null)
  					connA.Close ();
  				if (connB != null)
  					connB.Close ();
  			}
  		}
  
  		[Test]
  		public void ExecuteNonQuery_Transaction_Only ()
  		{
  			conn = new SqlConnection (connectionString);
  			conn.Open ();
  
  			SqlTransaction trans = conn.BeginTransaction ();
  
  			cmd = new SqlCommand ("select @@version");
  			cmd.Transaction = trans;
  
  			try {
  				cmd.ExecuteNonQuery ();
  				Assert.Fail ("#1");
  			} catch (InvalidOperationException ex) {
  				// ExecuteNonQuery: Connection property has not
  				// been initialized
  				Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
  				Assert.IsNull (ex.InnerException, "#3");
  				Assert.IsNotNull (ex.Message, "#4");
  				Assert.IsTrue (ex.Message.StartsWith ("ExecuteNonQuery:"), "#5");
  			} finally {
  				trans.Dispose ();
  			}
  		}
  
  		[Test] // bug #412569
  		public void ExecuteReader ()
  		{
  			// Test for command behaviors
  			DataTable schemaTable = null;
  			SqlDataReader reader = null;
  
  			conn = new SqlConnection (connectionString);
  			conn.Open ();
  			cmd = new SqlCommand ("", conn);
  			cmd.CommandText = "Select id from numeric_family where id <=4 order by id asc;";
  			cmd.CommandText += "Select type_bit from numeric_family where id <=4 order by id asc";
  
  			// Test for default command behavior
  			reader = cmd.ExecuteReader ();
  			int rows = 0;
  			int results = 0;
  			do {
  				while (reader.Read ())
  					rows++;
  				Assert.AreEqual (4, rows, "#1 Multiple rows shud be returned");
  				results++;
  				rows = 0;
  			} while (reader.NextResult ());
  			Assert.AreEqual (2, results, "#2 Multiple result sets shud be returned");
  			reader.Close ();
  
  			// Test if closing reader, closes the connection
  			reader = cmd.ExecuteReader (CommandBehavior.CloseConnection);
  			reader.Close ();
  			Assert.AreEqual (ConnectionState.Closed, conn.State,
  				"#3 Command Behavior is not followed");
  			conn.Open ();
  
  			// Test if row info and primary Key info is returned
  			reader = cmd.ExecuteReader (CommandBehavior.KeyInfo);
  			schemaTable = reader.GetSchemaTable ();
  			Assert.IsTrue (reader.HasRows, "#4 Data Rows shud also be returned");
  			Assert.IsTrue ((bool) schemaTable.Rows [0] ["IsKey"],
  				"#5 Primary Key info shud be returned");
  			reader.Close ();
  
  			// Test only column information is returned 
  			reader = cmd.ExecuteReader (CommandBehavior.SchemaOnly);
  			schemaTable = reader.GetSchemaTable ();
  			Assert.IsFalse (reader.HasRows, "#6 row data shud not be returned");
  			Assert.AreEqual (DBNull.Value, schemaTable.Rows [0] ["IsKey"],
  				"#7 Primary Key info shud not be returned");
  			Assert.AreEqual ("id", schemaTable.Rows [0] ["ColumnName"],
  				"#8 Schema Data is Incorrect");
  			reader.Close ();
  
  			// Test only one result set (first) is returned 
  			reader = cmd.ExecuteReader (CommandBehavior.SingleResult);
  			schemaTable = reader.GetSchemaTable ();
  			Assert.IsFalse (reader.NextResult (),
  				"#9 Only one result set shud be returned");
  			Assert.AreEqual ("id", schemaTable.Rows [0] ["ColumnName"],
  				"#10 The result set returned shud be the first result set");
  			reader.Close ();
  
  			// Test only one row is returned for all result sets 
  			// msdotnet doesnt work correctly.. returns only one result set
  			reader = cmd.ExecuteReader (CommandBehavior.SingleRow);
  			rows = 0;
  			results = 0;
  			do {
  				while (reader.Read ())
  					rows++;
  				Assert.AreEqual (1, rows, "#11 Only one row shud be returned");
  				results++;
  				rows = 0;
  			} while (reader.NextResult ());
  
  			// LAMESPEC:
  			// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=357085
  			Assert.AreEqual (1, results, "#12 Multiple result sets shud be returned");
  			reader.Close ();
  		}
  
  		[Test]
  		public void ExecuteReader_Connection_PendingTransaction ()
  		{
  			conn = new SqlConnection (connectionString);
  			conn.Open ();
  
  			using (SqlTransaction trans = conn.BeginTransaction ()) {
  				cmd = new SqlCommand ("select @@version", conn);
  
  				try {
  					cmd.ExecuteReader ();
  					Assert.Fail ("#1");
  				} catch (InvalidOperationException ex) {
  					// ExecuteReader requires the command
  					// to have a transaction object when the
  					// connection assigned to the command is
  					// in a pending local transaction.  The
  					// Transaction property of the command
  					// has not been initialized
  					Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
  					Assert.IsNull (ex.InnerException, "#3");
  					Assert.IsNotNull (ex.Message, "#4");
  #if NET_2_0
  					Assert.IsTrue (ex.Message.IndexOf ("ExecuteReader") != -1, "#5:" + ex.Message);
  #else
  					Assert.IsTrue (ex.Message.IndexOf ("Execute") != -1, "#5:" + ex.Message);
  #endif
  				}
  			}
  		}
  
  		[Test]
  		public void ExecuteReader_Query_Invalid ()
  		{
  			conn = new SqlConnection (connectionString);
  			conn.Open ();
  
  			cmd = new SqlCommand ("InvalidQuery", conn);
  			try {
  				cmd.ExecuteReader ();
  				Assert.Fail ("#A1");
  			} catch (SqlException ex) {
  				// Could not find stored procedure 'InvalidQuery'
  				Assert.AreEqual (typeof (SqlException), ex.GetType (), "#A2");
  				Assert.AreEqual ((byte) 16, ex.Class, "#A3");
  				Assert.IsNull (ex.InnerException, "#A4");
  				Assert.IsNotNull (ex.Message, "#A5");
  				Assert.IsTrue (ex.Message.IndexOf ("'InvalidQuery'") != -1, "#A6:" + ex.Message);
  				Assert.AreEqual (2812, ex.Number, "#A7");
  				Assert.AreEqual ((byte) 62, ex.State, "#A8");
  
  				// connection is not closed
  				Assert.AreEqual (ConnectionState.Open, conn.State, "#A9");
  			}
  
  			try {
  				cmd.ExecuteReader (CommandBehavior.CloseConnection);
  				Assert.Fail ("#B1");
  			} catch (SqlException ex) {
  				// Could not find stored procedure 'InvalidQuery'
  				Assert.AreEqual (typeof (SqlException), ex.GetType (), "#B2");
  				Assert.AreEqual ((byte) 16, ex.Class, "#B3");
  				Assert.IsNull (ex.InnerException, "#B4");
  				Assert.IsNotNull (ex.Message, "#B5");
  				Assert.IsTrue (ex.Message.IndexOf ("'InvalidQuery'") != -1, "#B6:" + ex.Message);
  				Assert.AreEqual (2812, ex.Number, "#B7");
  				Assert.AreEqual ((byte) 62, ex.State, "#B8");
  
  				// connection is closed
  				Assert.AreEqual (ConnectionState.Closed, conn.State, "#B9");
  			}
  		}
  
  		[Test]
  		public void ExecuteReader_Transaction_NotAssociated ()
  		{
  			SqlTransaction trans = null;
  			SqlConnection connA = null;
  			SqlConnection connB = null;
  
  			try {
  				connA = new SqlConnection (connectionString);
  				connA.Open ();
  
  				connB = new SqlConnection (connectionString);
  				connB.Open ();
  
  				trans = connA.BeginTransaction ();
  
  				cmd = new SqlCommand ("select @@version", connB, trans);
  
  				try {
  					cmd.ExecuteReader ();
  					Assert.Fail ("#A1");
  				} catch (InvalidOperationException ex) {
  					// The transaction object is not associated
  					// with the connection object
  					Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#A2");
  					Assert.IsNull (ex.InnerException, "#A3");
  					Assert.IsNotNull (ex.Message, "#A4");
  				} finally {
  					cmd.Dispose ();
  				}
  
  				cmd = new SqlCommand ("select @@version", connB);
  				cmd.Transaction = trans;
  
  				try {
  					cmd.ExecuteReader ();
  					Assert.Fail ("#B1");
  				} catch (InvalidOperationException ex) {
  					// The transaction object is not associated
  					// with the connection object
  					Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#B2");
  					Assert.IsNull (ex.InnerException, "#B3");
  					Assert.IsNotNull (ex.Message, "#B4");
  				} finally {
  					cmd.Dispose ();
  				}
  			} finally {
  				if (trans != null)
  					trans.Dispose ();
  
gt: 				if (connA != null)