Просмотр исходного кода

2002-11-26 Tim Coleman <[email protected]>
* System.Data.SqlClient/SqlCommand.cs:
* System.Data.SqlClient/SqlConnection.cs:
* System.Data.SqlClient/SqlDataReader.cs:
* System.Data.SqlClient/SqlParameter.cs:
* System.Data.SqlClient/SqlParameterCollection.cs:
* System.Data.SqlClient/SqlTransaction.cs:
Many changes around restructuring of parameter
information so that the Sybase provider supports
PREPAREs too.

svn path=/trunk/mcs/; revision=9193

Tim Coleman 23 лет назад
Родитель
Сommit
db177b4a47

+ 11 - 0
mcs/class/System.Data/ChangeLog

@@ -1,3 +1,14 @@
+2002-11-26  Tim Coleman <[email protected]>
+	* System.Data.SqlClient/SqlCommand.cs:
+	* System.Data.SqlClient/SqlConnection.cs:
+	* System.Data.SqlClient/SqlDataReader.cs:
+	* System.Data.SqlClient/SqlParameter.cs:
+	* System.Data.SqlClient/SqlParameterCollection.cs:
+	* System.Data.SqlClient/SqlTransaction.cs:
+		Many changes around restructuring of parameter
+		information so that the Sybase provider supports
+		PREPAREs too.
+
 2002-11-25  Ville Palo <[email protected]>
 2002-11-25  Ville Palo <[email protected]>
 
 
 	* System.Data/DataSet.cs : Started to implement ReadXmlSchema -method
 	* System.Data/DataSet.cs : Started to implement ReadXmlSchema -method

+ 63 - 193
mcs/class/System.Data/System.Data.SqlClient/SqlCommand.cs

@@ -11,6 +11,7 @@
 // Copyright (C) Tim Coleman, 2002
 // Copyright (C) Tim Coleman, 2002
 //
 //
 
 
+using Mono.Data.Tds;
 using Mono.Data.Tds.Protocol;
 using Mono.Data.Tds.Protocol;
 using System;
 using System;
 using System.Collections;
 using System.Collections;
@@ -28,19 +29,16 @@ namespace System.Data.SqlClient {
 		#region Fields
 		#region Fields
 
 
 		bool disposed = false;
 		bool disposed = false;
-
 		int commandTimeout;
 		int commandTimeout;
 		bool designTimeVisible;
 		bool designTimeVisible;
 		string commandText;
 		string commandText;
-
 		CommandType commandType;
 		CommandType commandType;
 		SqlConnection connection;
 		SqlConnection connection;
 		SqlTransaction transaction;
 		SqlTransaction transaction;
 		UpdateRowSource updatedRowSource;
 		UpdateRowSource updatedRowSource;
-
 		CommandBehavior behavior = CommandBehavior.Default;
 		CommandBehavior behavior = CommandBehavior.Default;
-		NameValueCollection preparedStatements = new NameValueCollection ();
 		SqlParameterCollection parameters;
 		SqlParameterCollection parameters;
+		string preparedStatement = null;
 
 
 		#endregion // Fields
 		#endregion // Fields
 
 
@@ -90,7 +88,11 @@ namespace System.Data.SqlClient {
 		[RefreshProperties (RefreshProperties.All)]
 		[RefreshProperties (RefreshProperties.All)]
 		public string CommandText {
 		public string CommandText {
 			get { return commandText; }
 			get { return commandText; }
-			set { commandText = value; }
+			set { 
+				if (value != commandText && preparedStatement != null)
+					Unprepare ();
+				commandText = value; 
+			}
 		}
 		}
 
 
 		[DataSysDescription ("Time to wait for command to execute.")]
 		[DataSysDescription ("Time to wait for command to execute.")]
@@ -191,137 +193,6 @@ namespace System.Data.SqlClient {
 
 
 		#region Methods
 		#region Methods
 
 
-		private string BuildCommand ()
-		{
-			string statementHandle = preparedStatements [commandText];
-			if (statementHandle != null) {
-				string proc = String.Format ("sp_execute {0}", statementHandle);	
-				if (parameters.Count > 0)
-					proc += ",";
-				return BuildProcedureCall (proc, parameters);
-			}
-
-			if (commandType == CommandType.StoredProcedure)
-				return BuildProcedureCall (commandText, parameters);
-
-			string sql = String.Empty;
-			if ((behavior & CommandBehavior.KeyInfo) > 0)
-				sql += "SET FMTONLY OFF; SET NO_BROWSETABLE ON;";
-			if ((behavior & CommandBehavior.SchemaOnly) > 0)
-				sql += "SET FMTONLY ON;";
-	
-			switch (commandType) {
-			case CommandType.Text :
-				sql += commandText;
-				break;
-			default:
-				throw new InvalidOperationException ("The CommandType was invalid.");
-			}
-			return BuildExec (sql);
-		}
-
-		private string BuildExec (string sql)
-		{
-			StringBuilder parms = new StringBuilder ();
-			foreach (SqlParameter parameter in parameters) {
-				if (parms.Length > 0)
-					parms.Append (", ");
-				parms.Append (parameter.Prepare (parameter.ParameterName));
-				if (parameter.Direction == ParameterDirection.Output)
-					parms.Append (" output");
-			}
-
-			SqlParameterCollection localParameters = new SqlParameterCollection (this);
-		
-			localParameters.Add ("@P1", SqlDbType.NVarChar, sql.Length).Value = sql;
-
-			if (parameters.Count > 0) 
-				localParameters.Add ("@P2", SqlDbType.NVarChar, parms.ToString ().Length).Value = parms.ToString ();
-
-			foreach (SqlParameter p in parameters)
-				localParameters.Add ((SqlParameter) ((ICloneable) p).Clone ());
-
-			return BuildProcedureCall ("sp_executesql", localParameters);
-		}
-
-		private string BuildPrepare ()
-		{
-			StringBuilder parms = new StringBuilder ();
-			foreach (SqlParameter parameter in parameters) {
-				if (parms.Length > 0)
-					parms.Append (", ");
-				parms.Append (parameter.Prepare (parameter.ParameterName));
-				if (parameter.Direction == ParameterDirection.Output)
-					parms.Append (" output");
-			}
-
-			SqlParameterCollection localParameters = new SqlParameterCollection (this);
-			SqlParameter parm;
-		
-			parm = new SqlParameter ("@P1", SqlDbType.Int);
-			parm.Direction = ParameterDirection.Output;
-			localParameters.Add (parm);
-
-			parm = new SqlParameter ("@P2", SqlDbType.NVarChar);
-			parm.Value = parms.ToString ();
-			parm.Size = ((string) parm.Value).Length;
-			localParameters.Add (parm);
-
-			parm = new SqlParameter ("@P3", SqlDbType.NVarChar);
-			parm.Value = commandText;
-			parm.Size = ((string) parm.Value).Length;
-			localParameters.Add (parm);
-
-			return BuildProcedureCall ("sp_prepare", localParameters);
-		}
-
-		private static string BuildProcedureCall (string procedure, SqlParameterCollection parameters)
-		{
-			StringBuilder parms = new StringBuilder ();
-			StringBuilder declarations = new StringBuilder ();
-			StringBuilder outParms = new StringBuilder ();
-			StringBuilder set = new StringBuilder ();
-
-			int index = 1;
-			foreach (SqlParameter parameter in parameters) {
-				string parmName = String.Format ("@P{0}", index);
-
-				switch (parameter.Direction) {
-				case ParameterDirection.Input :
-					if (parms.Length > 0)
-						parms.Append (", ");
-					parms.Append (FormatParameter (parameter));
-					break;
-				case ParameterDirection.Output :
-					if (parms.Length > 0)
-						parms.Append (", ");
-					parms.Append (parmName);
-					parms.Append (" output");
-
-					if (outParms.Length > 0) {
-						outParms.Append (", ");
-						declarations.Append (", ");
-					}
-					else {
-						outParms.Append ("select ");
-						declarations.Append ("declare ");
-					}
-
-					declarations.Append (parameter.Prepare (parmName));
-					set.Append (String.Format ("set {0}=NULL\n", parmName));
-					outParms.Append (parmName);
-					break;
-				default :
-					throw new NotImplementedException ("Only support input and output parameters.");
-				}
-				index += 1;
-			}
-			if (declarations.Length > 0)
-				declarations.Append ('\n');
-
-			return String.Format ("{0}{1}{2} {3}\n{4}", declarations.ToString (), set.ToString (), procedure, parms.ToString (), outParms.ToString ());
-		}
-
 		public void Cancel () 
 		public void Cancel () 
 		{
 		{
 			if (Connection == null || Connection.Tds == null)
 			if (Connection == null || Connection.Tds == null)
@@ -352,7 +223,10 @@ namespace System.Data.SqlClient {
 			SqlParameterCollection localParameters = new SqlParameterCollection (this);
 			SqlParameterCollection localParameters = new SqlParameterCollection (this);
 			localParameters.Add ("@P1", SqlDbType.NVarChar, commandText.Length).Value = commandText;
 			localParameters.Add ("@P1", SqlDbType.NVarChar, commandText.Length).Value = commandText;
 
 
-			Connection.Tds.ExecuteQuery (BuildProcedureCall ("sp_procedure_params_rowset", localParameters));
+			string sql = "sp_procedure_params_rowset";
+
+			Connection.Tds.ExecProc (sql, localParameters.MetaParameters, 0, true);
+
 			SqlDataReader reader = new SqlDataReader (this);
 			SqlDataReader reader = new SqlDataReader (this);
 			parameters.Clear ();
 			parameters.Clear ();
 			object[] dbValues = new object[reader.FieldCount];
 			object[] dbValues = new object[reader.FieldCount];
@@ -364,19 +238,52 @@ namespace System.Data.SqlClient {
 			reader.Close ();	
 			reader.Close ();	
 		}
 		}
 
 
+		private void Execute (CommandBehavior behavior, bool wantResults)
+		{
+			TdsMetaParameterCollection parms = Parameters.MetaParameters;
+			if (preparedStatement == null) {
+				bool schemaOnly = ((CommandBehavior & CommandBehavior.SchemaOnly) > 0);
+				bool keyInfo = ((CommandBehavior & CommandBehavior.SchemaOnly) > 0);
+
+				StringBuilder sql1 = new StringBuilder ();
+				StringBuilder sql2 = new StringBuilder ();
+
+				if (schemaOnly || keyInfo)
+					sql1.Append ("SET FMTONLY OFF;");
+				if (keyInfo) {
+					sql1.Append ("SET NO_BROWSETABLE ON;");
+					sql2.Append ("SET NO_BROWSETABLE OFF;");
+				}
+				if (schemaOnly) {
+					sql1.Append ("SET FMTONLY ON;");
+					sql2.Append ("SET FMTONLY OFF;");
+				}
+
+				switch (CommandType) {
+				case CommandType.StoredProcedure:
+					if (keyInfo || schemaOnly)
+						Connection.Tds.Execute (sql1.ToString ());
+					Connection.Tds.ExecProc (CommandText, parms, CommandTimeout, wantResults);
+					if (keyInfo || schemaOnly)
+						Connection.Tds.Execute (sql2.ToString ());
+					break;
+				case CommandType.Text:
+					string sql = String.Format ("{0}{1}{2}", sql1.ToString (), CommandText, sql2.ToString ());
+					Connection.Tds.Execute (sql, parms, CommandTimeout, wantResults);
+					break;
+				}
+			}
+			else 
+				Connection.Tds.ExecPrepared (preparedStatement, parms, CommandTimeout, wantResults);
+		}
+
 		public int ExecuteNonQuery ()
 		public int ExecuteNonQuery ()
 		{
 		{
 			ValidateCommand ("ExecuteNonQuery");
 			ValidateCommand ("ExecuteNonQuery");
-			string sql = String.Empty;
 			int result = 0;
 			int result = 0;
 
 
-			if (Parameters.Count > 0)
-				sql = BuildCommand ();
-			else
-				sql = CommandText;
-
 			try {
 			try {
-				result = Connection.Tds.ExecuteNonQuery (sql, CommandTimeout);
+				Execute (CommandBehavior.Default, false);
 			}
 			}
 			catch (TdsTimeoutException e) {
 			catch (TdsTimeoutException e) {
 				throw SqlException.FromTdsInternalException ((TdsInternalException) e);
 				throw SqlException.FromTdsInternalException ((TdsInternalException) e);
@@ -394,15 +301,12 @@ namespace System.Data.SqlClient {
 		public SqlDataReader ExecuteReader (CommandBehavior behavior)
 		public SqlDataReader ExecuteReader (CommandBehavior behavior)
 		{
 		{
 			ValidateCommand ("ExecuteReader");
 			ValidateCommand ("ExecuteReader");
-			this.behavior = behavior;
-
 			try {
 			try {
-				Connection.Tds.ExecuteQuery (BuildCommand (), CommandTimeout);
+				Execute (behavior, true);
 			}
 			}
 			catch (TdsTimeoutException e) {
 			catch (TdsTimeoutException e) {
 				throw SqlException.FromTdsInternalException ((TdsInternalException) e);
 				throw SqlException.FromTdsInternalException ((TdsInternalException) e);
 			}
 			}
-		
 			Connection.DataReader = new SqlDataReader (this);
 			Connection.DataReader = new SqlDataReader (this);
 			return Connection.DataReader;
 			return Connection.DataReader;
 		}
 		}
@@ -411,7 +315,7 @@ namespace System.Data.SqlClient {
 		{
 		{
 			ValidateCommand ("ExecuteScalar");
 			ValidateCommand ("ExecuteScalar");
 			try {
 			try {
-				Connection.Tds.ExecuteQuery (BuildCommand (), CommandTimeout);
+				Execute (CommandBehavior.Default, true);
 			}
 			}
 			catch (TdsTimeoutException e) {
 			catch (TdsTimeoutException e) {
 				throw SqlException.FromTdsInternalException ((TdsInternalException) e);
 				throw SqlException.FromTdsInternalException ((TdsInternalException) e);
@@ -428,9 +332,8 @@ namespace System.Data.SqlClient {
 		public XmlReader ExecuteXmlReader ()
 		public XmlReader ExecuteXmlReader ()
 		{
 		{
 			ValidateCommand ("ExecuteXmlReader");
 			ValidateCommand ("ExecuteXmlReader");
-
-			try {
-				Connection.Tds.ExecuteQuery (BuildCommand (), CommandTimeout);
+			try { 
+				Execute (CommandBehavior.Default, true);
 			}
 			}
 			catch (TdsTimeoutException e) {
 			catch (TdsTimeoutException e) {
 				throw SqlException.FromTdsInternalException ((TdsInternalException) e);
 				throw SqlException.FromTdsInternalException ((TdsInternalException) e);
@@ -442,41 +345,6 @@ namespace System.Data.SqlClient {
 			return xmlReader;
 			return xmlReader;
 		}
 		}
 
 
-		[MonoTODO ("Include offset from SqlParameter for binary/string types.")]
-		static string FormatParameter (SqlParameter parameter)
-		{
-			if (parameter.Value == null)
-				return "NULL";
-
-			switch (parameter.SqlDbType) {
-				case SqlDbType.BigInt :
-				case SqlDbType.Decimal :
-				case SqlDbType.Float :
-				case SqlDbType.Int :
-				case SqlDbType.Money :
-				case SqlDbType.Real :
-				case SqlDbType.SmallInt :
-				case SqlDbType.SmallMoney :
-				case SqlDbType.TinyInt :
-					return parameter.Value.ToString ();
-				case SqlDbType.NVarChar :
-				case SqlDbType.NChar :
-					return String.Format ("N'{0}'", parameter.Value.ToString ().Replace ("'", "''"));
-				case SqlDbType.UniqueIdentifier :
-					return String.Format ("0x{0}", ((Guid) parameter.Value).ToString ("N"));
-				case SqlDbType.Bit:
-					if (parameter.Value.GetType () == typeof (bool))
-						return (((bool) parameter.Value) ? "0x1" : "0x0");
-					return parameter.Value.ToString ();
-				case SqlDbType.Image:
-				case SqlDbType.Binary:
-				case SqlDbType.VarBinary:
-					return String.Format ("0x{0}", BitConverter.ToString ((byte[]) parameter.Value).Replace ("-", "").ToLower ());
-				default:
-					return String.Format ("'{0}'", parameter.Value.ToString ().Replace ("'", "''"));
-			}
-		}
-
 		private void GetOutputParameters ()
 		private void GetOutputParameters ()
 		{
 		{
 			Connection.Tds.SkipToEnd ();
 			Connection.Tds.SkipToEnd ();
@@ -519,12 +387,8 @@ namespace System.Data.SqlClient {
 		public void Prepare ()
 		public void Prepare ()
 		{
 		{
 			ValidateCommand ("Prepare");
 			ValidateCommand ("Prepare");
-			Connection.Tds.ExecuteNonQuery (BuildPrepare ());
-
-			if (Connection.Tds.OutputParameters.Count == 0 || Connection.Tds.OutputParameters[0] == null)
-				throw new Exception ("Could not prepare the statement.");
-
-			preparedStatements [commandText] = ((int) Connection.Tds.OutputParameters [0]).ToString ();
+			if (CommandType == CommandType.Text) 
+				preparedStatement = Connection.Tds.Prepare (CommandText, Parameters.MetaParameters);
 		}
 		}
 
 
 		public void ResetCommandTimeout ()
 		public void ResetCommandTimeout ()
@@ -532,6 +396,12 @@ namespace System.Data.SqlClient {
 			commandTimeout = 30;
 			commandTimeout = 30;
 		}
 		}
 
 
+		private void Unprepare ()
+		{
+			Connection.Tds.Unprepare (preparedStatement);
+			preparedStatement = null;
+		}
+
 		private void ValidateCommand (string method)
 		private void ValidateCommand (string method)
 		{
 		{
 			if (Connection == null)
 			if (Connection == null)

+ 4 - 3
mcs/class/System.Data/System.Data.SqlClient/SqlConnection.cs

@@ -11,6 +11,7 @@
 // Copyright (C) Tim Coleman, 2002
 // Copyright (C) Tim Coleman, 2002
 //
 //
 
 
+using Mono.Data.Tds;
 using Mono.Data.Tds.Protocol;
 using Mono.Data.Tds.Protocol;
 using System;
 using System;
 using System.Collections;
 using System.Collections;
@@ -224,7 +225,7 @@ namespace System.Data.SqlClient {
 				break;
 				break;
 			}
 			}
 
 
-			tds.ExecuteNonQuery (String.Format ("SET TRANSACTION ISOLATION LEVEL {0};BEGIN TRANSACTION {1}", isolevel, transactionName));
+			tds.Execute (String.Format ("SET TRANSACTION ISOLATION LEVEL {0};BEGIN TRANSACTION {1}", isolevel, transactionName));
 
 
 			transaction = new SqlTransaction (this, iso);
 			transaction = new SqlTransaction (this, iso);
 			return transaction;
 			return transaction;
@@ -236,7 +237,7 @@ namespace System.Data.SqlClient {
 				throw new ArgumentException (String.Format ("The database name {0} is not valid."));
 				throw new ArgumentException (String.Format ("The database name {0} is not valid."));
 			if (state != ConnectionState.Open)
 			if (state != ConnectionState.Open)
 				throw new InvalidOperationException ("The connection is not open.");
 				throw new InvalidOperationException ("The connection is not open.");
-			tds.ExecuteNonQuery (String.Format ("use {0}", database));
+			tds.Execute (String.Format ("use {0}", database));
 		}
 		}
 
 
 		private void ChangeState (ConnectionState currentState)
 		private void ChangeState (ConnectionState currentState)
@@ -351,7 +352,7 @@ namespace System.Data.SqlClient {
 			if (!tds.IsConnected) 
 			if (!tds.IsConnected) 
 				tds.Connect (parms);
 				tds.Connect (parms);
 			else if (connectionReset)
 			else if (connectionReset)
-				tds.ExecuteNonQuery ("EXEC sp_reset_connection");
+				tds.ExecProc ("sp_reset_connection");
 				
 				
 			ChangeState (ConnectionState.Open);
 			ChangeState (ConnectionState.Open);
 		}
 		}

+ 49 - 31
mcs/class/System.Data/System.Data.SqlClient/SqlDataReader.cs

@@ -320,6 +320,55 @@ namespace System.Data.SqlClient {
 					row ["BaseColumnName"] = row ["ColumnName"];
 					row ["BaseColumnName"] = row ["ColumnName"];
 
 
 				switch ((TdsColumnType) schema ["ColumnType"]) {
 				switch ((TdsColumnType) schema ["ColumnType"]) {
+					case TdsColumnType.Int1:
+					case TdsColumnType.Int2:
+					case TdsColumnType.Int4:
+					case TdsColumnType.IntN:
+						switch ((int) schema ["ColumnSize"]) {
+						case 1:
+							dataTypeNames.Add ("tinyint");
+							row ["ProviderType"] = (int) SqlDbType.TinyInt;
+							row ["DataType"] = typeof (byte);
+							row ["IsLong"] = false;
+							break;
+						case 2:
+							dataTypeNames.Add ("smallint");
+							row ["ProviderType"] = (int) SqlDbType.SmallInt;
+							row ["DataType"] = typeof (short);
+							row ["IsLong"] = false;
+							break;
+						case 4:
+							dataTypeNames.Add ("int");
+							row ["ProviderType"] = (int) SqlDbType.Int;
+							row ["DataType"] = typeof (int);
+							row ["IsLong"] = false;
+							break;
+						case 8:
+							dataTypeNames.Add ("bigint");
+							row ["ProviderType"] = (int) SqlDbType.BigInt;
+							row ["DataType"] = typeof (long);
+							row ["IsLong"] = false;
+							break;
+						}
+						break;
+					case TdsColumnType.Real:
+					case TdsColumnType.Float8:
+					case TdsColumnType.FloatN:
+						switch ((int) schema ["ColumnSize"]) {
+						case 4:
+							dataTypeNames.Add ("real");
+							row ["ProviderType"] = (int) SqlDbType.Real;
+							row ["DataType"] = typeof (float);
+							row ["IsLong"] = false;
+							break;
+						case 8:
+							dataTypeNames.Add ("float");
+							row ["ProviderType"] = (int) SqlDbType.Float;
+							row ["DataType"] = typeof (double);
+							row ["IsLong"] = false;
+							break;
+						}
+						break;
 					case TdsColumnType.Image :
 					case TdsColumnType.Image :
 						dataTypeNames.Add ("image");
 						dataTypeNames.Add ("image");
 						row ["ProviderType"] = (int) SqlDbType.Image;
 						row ["ProviderType"] = (int) SqlDbType.Image;
@@ -345,13 +394,6 @@ namespace System.Data.SqlClient {
 						row ["DataType"] = typeof (byte[]);
 						row ["DataType"] = typeof (byte[]);
 						row ["IsLong"] = true;
 						row ["IsLong"] = true;
 						break;
 						break;
-					case TdsColumnType.IntN :
-					case TdsColumnType.Int4 :
-						dataTypeNames.Add ("int");
-						row ["ProviderType"] = (int) SqlDbType.Int;
-						row ["DataType"] = typeof (int);
-						row ["IsLong"] = false;
-						break;
 					case TdsColumnType.VarChar :
 					case TdsColumnType.VarChar :
 					case TdsColumnType.BigVarChar :
 					case TdsColumnType.BigVarChar :
 						dataTypeNames.Add ("varchar");
 						dataTypeNames.Add ("varchar");
@@ -373,12 +415,6 @@ namespace System.Data.SqlClient {
 						row ["DataType"] = typeof (string);
 						row ["DataType"] = typeof (string);
 						row ["IsLong"] = false;
 						row ["IsLong"] = false;
 						break;
 						break;
-					case TdsColumnType.Int1 :
-						dataTypeNames.Add ("tinyint");
-						row ["ProviderType"] = (int) SqlDbType.TinyInt;
-						row ["DataType"] = typeof (byte);
-						row ["IsLong"] = false;
-						break;
 					case TdsColumnType.Bit :
 					case TdsColumnType.Bit :
 					case TdsColumnType.BitN :
 					case TdsColumnType.BitN :
 						dataTypeNames.Add ("bit");
 						dataTypeNames.Add ("bit");
@@ -386,12 +422,6 @@ namespace System.Data.SqlClient {
 						row ["DataType"] = typeof (bool);
 						row ["DataType"] = typeof (bool);
 						row ["IsLong"] = false;
 						row ["IsLong"] = false;
 						break;
 						break;
-					case TdsColumnType.Int2 :
-						dataTypeNames.Add ("smallint");
-						row ["ProviderType"] = (int) SqlDbType.SmallInt;
-						row ["DataType"] = typeof (short);
-						row ["IsLong"] = false;
-						break;
 					case TdsColumnType.DateTime4 :
 					case TdsColumnType.DateTime4 :
 					case TdsColumnType.DateTime :
 					case TdsColumnType.DateTime :
 					case TdsColumnType.DateTimeN :
 					case TdsColumnType.DateTimeN :
@@ -400,11 +430,6 @@ namespace System.Data.SqlClient {
 						row ["DataType"] = typeof (DateTime);
 						row ["DataType"] = typeof (DateTime);
 						row ["IsLong"] = false;
 						row ["IsLong"] = false;
 						break;
 						break;
-					case TdsColumnType.Real :
-						dataTypeNames.Add ("real");
-						row ["ProviderType"] = (int) SqlDbType.Real;
-						row ["DataType"] = typeof (float);
-						break;
 					case TdsColumnType.Money :
 					case TdsColumnType.Money :
 					case TdsColumnType.MoneyN :
 					case TdsColumnType.MoneyN :
 					case TdsColumnType.Money4 :
 					case TdsColumnType.Money4 :
@@ -413,13 +438,6 @@ namespace System.Data.SqlClient {
 						row ["DataType"] = typeof (decimal);
 						row ["DataType"] = typeof (decimal);
 						row ["IsLong"] = false;
 						row ["IsLong"] = false;
 						break;
 						break;
-					case TdsColumnType.Float8 :
-					case TdsColumnType.FloatN :
-						dataTypeNames.Add ("float");
-						row ["ProviderType"] = (int) SqlDbType.Float;
-						row ["DataType"] = typeof (double);
-						row ["IsLong"] = false;
-						break;
 					case TdsColumnType.NText :
 					case TdsColumnType.NText :
 						dataTypeNames.Add ("ntext");
 						dataTypeNames.Add ("ntext");
 						row ["ProviderType"] = (int) SqlDbType.NText;
 						row ["ProviderType"] = (int) SqlDbType.NText;

+ 83 - 118
mcs/class/System.Data/System.Data.SqlClient/SqlParameter.cs

@@ -10,6 +10,7 @@
 // Copyright (C) Tim Coleman, 2002
 // Copyright (C) Tim Coleman, 2002
 //
 //
 
 
+using Mono.Data.Tds;
 using Mono.Data.Tds.Protocol;
 using Mono.Data.Tds.Protocol;
 using System;
 using System;
 using System.ComponentModel;
 using System.ComponentModel;
@@ -23,22 +24,18 @@ namespace System.Data.SqlClient {
 	{
 	{
 		#region Fields
 		#region Fields
 
 
+		TdsMetaParameter metaParameter;
+
 		SqlParameterCollection container = null;
 		SqlParameterCollection container = null;
 		DbType dbType;
 		DbType dbType;
 		ParameterDirection direction = ParameterDirection.Input;
 		ParameterDirection direction = ParameterDirection.Input;
 		bool isNullable;
 		bool isNullable;
 		bool isSizeSet = false;
 		bool isSizeSet = false;
 		bool isTypeSet = false;
 		bool isTypeSet = false;
-		object objValue;
 		int offset;
 		int offset;
-		string parameterName;
-		byte precision;
-		byte scale;
-		int size;
 		SqlDbType sqlDbType;
 		SqlDbType sqlDbType;
 		string sourceColumn;
 		string sourceColumn;
 		DataRowVersion sourceVersion;
 		DataRowVersion sourceVersion;
-		string typeName;
 
 
 		#endregion // Fields
 		#endregion // Fields
 
 
@@ -51,8 +48,7 @@ namespace System.Data.SqlClient {
 
 
 		public SqlParameter (string parameterName, object value) 
 		public SqlParameter (string parameterName, object value) 
 		{
 		{
-			this.parameterName = parameterName;
-			this.objValue = value;
+			metaParameter = new TdsMetaParameter (parameterName, value);
 			this.sourceVersion = DataRowVersion.Current;
 			this.sourceVersion = DataRowVersion.Current;
 			InferSqlType (value);
 			InferSqlType (value);
 		}
 		}
@@ -75,15 +71,10 @@ namespace System.Data.SqlClient {
 		[EditorBrowsable (EditorBrowsableState.Advanced)]	 
 		[EditorBrowsable (EditorBrowsableState.Advanced)]	 
 		public SqlParameter (string parameterName, SqlDbType dbType, int size, ParameterDirection direction, bool isNullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value) 
 		public SqlParameter (string parameterName, SqlDbType dbType, int size, ParameterDirection direction, bool isNullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value) 
 		{
 		{
-			SqlDbType = dbType;
-			Size = size;
-			Value = value;
+			metaParameter = new TdsMetaParameter (parameterName, size, isNullable, precision, scale, value);
 
 
-			ParameterName = parameterName;
+			SqlDbType = dbType;
 			Direction = direction;
 			Direction = direction;
-			IsNullable = isNullable;
-			Precision = precision;
-			Scale = scale;
 			SourceColumn = sourceColumn;
 			SourceColumn = sourceColumn;
 			SourceVersion = sourceVersion;
 			SourceVersion = sourceVersion;
 		}
 		}
@@ -93,33 +84,33 @@ namespace System.Data.SqlClient {
 		// This is in SqlCommand.DeriveParameters.
 		// This is in SqlCommand.DeriveParameters.
 		internal SqlParameter (object[] dbValues)
 		internal SqlParameter (object[] dbValues)
 		{
 		{
-			precision = 0;
-			scale = 0;
-			direction = ParameterDirection.Input;
+			Precision = 0;
+			Scale = 0;
+			Direction = ParameterDirection.Input;
 
 
-			parameterName = (string) dbValues[3];
+			ParameterName = (string) dbValues[3];
 
 
 			switch ((short) dbValues[5]) {
 			switch ((short) dbValues[5]) {
 			case 1:
 			case 1:
-				direction = ParameterDirection.Input;
+				Direction = ParameterDirection.Input;
 				break;
 				break;
 			case 2:
 			case 2:
-				direction = ParameterDirection.Output;
+				Direction = ParameterDirection.Output;
 				break;
 				break;
 			case 3:
 			case 3:
-				direction = ParameterDirection.InputOutput;
+				Direction = ParameterDirection.InputOutput;
 				break;
 				break;
 			case 4:
 			case 4:
-				direction = ParameterDirection.ReturnValue;
+				Direction = ParameterDirection.ReturnValue;
 				break;
 				break;
 			}
 			}
 
 
-			isNullable = (bool) dbValues[8];
+			IsNullable = (bool) dbValues[8];
 
 
 			if (dbValues[12] != null)
 			if (dbValues[12] != null)
-				precision = (byte) ((short) dbValues[12]);
+				Precision = (byte) ((short) dbValues[12]);
 			if (dbValues[13] != null)
 			if (dbValues[13] != null)
-				scale = (byte) ((short) dbValues[13]);
+				Scale = (byte) ((short) dbValues[13]);
 
 
 			SetDbTypeName ((string) dbValues[16]);
 			SetDbTypeName ((string) dbValues[16]);
 		}
 		}
@@ -153,12 +144,20 @@ namespace System.Data.SqlClient {
 		[DefaultValue (ParameterDirection.Input)]
 		[DefaultValue (ParameterDirection.Input)]
 		public ParameterDirection Direction {
 		public ParameterDirection Direction {
 			get { return direction; }
 			get { return direction; }
-			set { direction = value; }
+			set { 
+				direction = value; 
+				if (direction == ParameterDirection.Output)
+					MetaParameter.Direction = TdsParameterDirection.Output;
+			}
+		}
+
+		internal TdsMetaParameter MetaParameter {
+			get { return metaParameter; }
 		}
 		}
 
 
 		string IDataParameter.ParameterName {
 		string IDataParameter.ParameterName {
-			get { return parameterName; }
-			set { parameterName = value; }
+			get { return metaParameter.ParameterName; }
+			set { metaParameter.ParameterName = value; }
 		}
 		}
 
 
 		[Browsable (false)]
 		[Browsable (false)]
@@ -167,8 +166,8 @@ namespace System.Data.SqlClient {
 		[DesignOnly (true)]
 		[DesignOnly (true)]
 		[EditorBrowsable (EditorBrowsableState.Advanced)]	 
 		[EditorBrowsable (EditorBrowsableState.Advanced)]	 
 		public bool IsNullable	{
 		public bool IsNullable	{
-			get { return isNullable; }
-			set { isNullable = value; }
+			get { return metaParameter.IsNullable; }
+			set { metaParameter.IsNullable = value; }
 		}
 		}
 
 
 		[Browsable (false)]
 		[Browsable (false)]
@@ -183,35 +182,32 @@ namespace System.Data.SqlClient {
 		[DataSysDescription ("Name of the parameter, like '@p1'")]
 		[DataSysDescription ("Name of the parameter, like '@p1'")]
 		[DefaultValue ("")]
 		[DefaultValue ("")]
 		public string ParameterName {
 		public string ParameterName {
-			get { return parameterName; }
-			set { parameterName = value; }
+			get { return metaParameter.ParameterName; }
+			set { metaParameter.ParameterName = value; }
 		}
 		}
 
 
 		[DataCategory ("Data")]
 		[DataCategory ("Data")]
 		[DataSysDescription ("For decimal, numeric, varnumeric DBTypes.")]
 		[DataSysDescription ("For decimal, numeric, varnumeric DBTypes.")]
 		[DefaultValue (0)]
 		[DefaultValue (0)]
 		public byte Precision {
 		public byte Precision {
-			get { return precision; }
-			set { precision = value; }
+			get { return metaParameter.Precision; }
+			set { metaParameter.Precision = value; }
 		}
 		}
 
 
 		[DataCategory ("Data")]
 		[DataCategory ("Data")]
 		[DataSysDescription ("For decimal, numeric, varnumeric DBTypes.")]
 		[DataSysDescription ("For decimal, numeric, varnumeric DBTypes.")]
 		[DefaultValue (0)]
 		[DefaultValue (0)]
                 public byte Scale {
                 public byte Scale {
-			get { return scale; }
-			set { scale = value; }
+			get { return metaParameter.Scale; }
+			set { metaParameter.Scale = value; }
 		}
 		}
 
 
 		[DataCategory ("Data")]
 		[DataCategory ("Data")]
 		[DataSysDescription ("Size of variable length datatypes (strings & arrays).")]
 		[DataSysDescription ("Size of variable length datatypes (strings & arrays).")]
 		[DefaultValue (0)]
 		[DefaultValue (0)]
                 public int Size {
                 public int Size {
-			get { return size; }
-			set { 
-				size = value; 
-				isSizeSet = true;
-			}
+			get { return metaParameter.Size; }
+			set { metaParameter.Size = value; }
 		}
 		}
 
 
 		[DataCategory ("Data")]
 		[DataCategory ("Data")]
@@ -246,11 +242,11 @@ namespace System.Data.SqlClient {
 		[DataSysDescription ("Value of the parameter.")]
 		[DataSysDescription ("Value of the parameter.")]
 		[DefaultValue (null)]
 		[DefaultValue (null)]
 		public object Value {
 		public object Value {
-			get { return objValue; }
+			get { return metaParameter.Value; }
 			set { 
 			set { 
 				if (!isTypeSet)
 				if (!isTypeSet)
 					InferSqlType (value);
 					InferSqlType (value);
-				objValue = value; 
+				metaParameter.Value = value; 
 			}
 			}
 		}
 		}
 
 
@@ -316,37 +312,6 @@ namespace System.Data.SqlClient {
 			}
 			}
 		}
 		}
 
 
-		internal string Prepare (string name)
-		{
-			StringBuilder result = new StringBuilder ();
-			result.Append (name);
-			result.Append (" ");
-			result.Append (typeName);
-
-			switch (sqlDbType) {
-			case SqlDbType.VarBinary :
-			case SqlDbType.NVarChar :
-			case SqlDbType.VarChar :
-				if (!isSizeSet || size == 0)
-					throw new InvalidOperationException ("All variable length parameters must have an explicitly set non-zero size.");
-				result.Append (String.Format ("({0})", size));
-				break;
-			case SqlDbType.NChar :
-			case SqlDbType.Char :
-			case SqlDbType.Binary :
-				if (size > 0) 
-					result.Append (String.Format ("({0})", size));
-				break;
-			case SqlDbType.Decimal :
-				result.Append (String.Format ("({0},{1})", precision, scale));
-				break;
-                        default:
-                                break;
-                        }
-
-                        return result.ToString ();
-		}
-
 		// When the DbType is set, we also set the SqlDbType, as well as the SQL Server
 		// When the DbType is set, we also set the SqlDbType, as well as the SQL Server
 		// string representation of the type name.  If the DbType is not convertible
 		// string representation of the type name.  If the DbType is not convertible
 		// to an SqlDbType, throw an exception.
 		// to an SqlDbType, throw an exception.
@@ -356,76 +321,76 @@ namespace System.Data.SqlClient {
 
 
 			switch (type) {
 			switch (type) {
 			case DbType.AnsiString:
 			case DbType.AnsiString:
-				typeName = "varchar";
+				MetaParameter.TypeName = "varchar";
 				sqlDbType = SqlDbType.VarChar;
 				sqlDbType = SqlDbType.VarChar;
 				break;
 				break;
 			case DbType.AnsiStringFixedLength:
 			case DbType.AnsiStringFixedLength:
-				typeName = "char";
+				MetaParameter.TypeName = "char";
 				sqlDbType = SqlDbType.Char;
 				sqlDbType = SqlDbType.Char;
 				break;
 				break;
 			case DbType.Binary:
 			case DbType.Binary:
-				typeName = "varbinary";
+				MetaParameter.TypeName = "varbinary";
 				sqlDbType = SqlDbType.VarBinary;
 				sqlDbType = SqlDbType.VarBinary;
 				break;
 				break;
 			case DbType.Boolean:
 			case DbType.Boolean:
-				typeName = "bit";
+				MetaParameter.TypeName = "bit";
 				sqlDbType = SqlDbType.Bit;
 				sqlDbType = SqlDbType.Bit;
 				break;
 				break;
 			case DbType.Byte:
 			case DbType.Byte:
-				typeName = "tinyint";
+				MetaParameter.TypeName = "tinyint";
 				sqlDbType = SqlDbType.TinyInt;
 				sqlDbType = SqlDbType.TinyInt;
 				break;
 				break;
 			case DbType.Currency:
 			case DbType.Currency:
 				sqlDbType = SqlDbType.Money;
 				sqlDbType = SqlDbType.Money;
-				typeName = "money";
+				MetaParameter.TypeName = "money";
 				break;
 				break;
 			case DbType.Date:
 			case DbType.Date:
 			case DbType.DateTime:
 			case DbType.DateTime:
-				typeName = "datetime";
+				MetaParameter.TypeName = "datetime";
 				sqlDbType = SqlDbType.DateTime;
 				sqlDbType = SqlDbType.DateTime;
 				break;
 				break;
 			case DbType.Decimal:
 			case DbType.Decimal:
-				typeName = "decimal";
+				MetaParameter.TypeName = "decimal";
 				sqlDbType = SqlDbType.Decimal;
 				sqlDbType = SqlDbType.Decimal;
 				break;
 				break;
 			case DbType.Double:
 			case DbType.Double:
-				typeName = "float";
+				MetaParameter.TypeName = "float";
 				sqlDbType = SqlDbType.Float;
 				sqlDbType = SqlDbType.Float;
 				break;
 				break;
 			case DbType.Guid:
 			case DbType.Guid:
-				typeName = "uniqueidentifier";
+				MetaParameter.TypeName = "uniqueidentifier";
 				sqlDbType = SqlDbType.UniqueIdentifier;
 				sqlDbType = SqlDbType.UniqueIdentifier;
 				break;
 				break;
 			case DbType.Int16:
 			case DbType.Int16:
-				typeName = "smallint";
+				MetaParameter.TypeName = "smallint";
 				sqlDbType = SqlDbType.SmallInt;
 				sqlDbType = SqlDbType.SmallInt;
 				break;
 				break;
 			case DbType.Int32:
 			case DbType.Int32:
-				typeName = "int";
+				MetaParameter.TypeName = "int";
 				sqlDbType = SqlDbType.Int;
 				sqlDbType = SqlDbType.Int;
 				break;
 				break;
 			case DbType.Int64:
 			case DbType.Int64:
-				typeName = "bigint";
+				MetaParameter.TypeName = "bigint";
 				sqlDbType = SqlDbType.BigInt;
 				sqlDbType = SqlDbType.BigInt;
 				break;
 				break;
 			case DbType.Object:
 			case DbType.Object:
-				typeName = "sql_variant";
+				MetaParameter.TypeName = "sql_variant";
 				sqlDbType = SqlDbType.Variant;
 				sqlDbType = SqlDbType.Variant;
 				break;
 				break;
 			case DbType.Single:
 			case DbType.Single:
-				typeName = "real";
+				MetaParameter.TypeName = "real";
 				sqlDbType = SqlDbType.Real;
 				sqlDbType = SqlDbType.Real;
 				break;
 				break;
 			case DbType.String:
 			case DbType.String:
-				typeName = "nvarchar";
+				MetaParameter.TypeName = "nvarchar";
 				sqlDbType = SqlDbType.NVarChar;
 				sqlDbType = SqlDbType.NVarChar;
 				break;
 				break;
 			case DbType.StringFixedLength:
 			case DbType.StringFixedLength:
-				typeName = "nchar";
+				MetaParameter.TypeName = "nchar";
 				sqlDbType = SqlDbType.NChar;
 				sqlDbType = SqlDbType.NChar;
 				break;
 				break;
 			case DbType.Time:
 			case DbType.Time:
-				typeName = "datetime";
+				MetaParameter.TypeName = "datetime";
 				sqlDbType = SqlDbType.DateTime;
 				sqlDbType = SqlDbType.DateTime;
 				break;
 				break;
 			default:
 			default:
@@ -522,99 +487,99 @@ namespace System.Data.SqlClient {
 
 
 			switch (type) {
 			switch (type) {
 			case SqlDbType.BigInt:
 			case SqlDbType.BigInt:
-				typeName = "bigint";
+				MetaParameter.TypeName = "bigint";
 				dbType = DbType.Int64;
 				dbType = DbType.Int64;
 				break;
 				break;
 			case SqlDbType.Binary:
 			case SqlDbType.Binary:
-				typeName = "binary";
+				MetaParameter.TypeName = "binary";
 				dbType = DbType.Binary;
 				dbType = DbType.Binary;
 				break;
 				break;
 			case SqlDbType.Timestamp:
 			case SqlDbType.Timestamp:
-				typeName = "timestamp";
+				MetaParameter.TypeName = "timestamp";
 				dbType = DbType.Binary;
 				dbType = DbType.Binary;
 				break;
 				break;
 			case SqlDbType.VarBinary:
 			case SqlDbType.VarBinary:
-				typeName = "varbinary";
+				MetaParameter.TypeName = "varbinary";
 				dbType = DbType.Binary;
 				dbType = DbType.Binary;
 				break;
 				break;
 			case SqlDbType.Bit:
 			case SqlDbType.Bit:
-				typeName = "bit";
+				MetaParameter.TypeName = "bit";
 				dbType = DbType.Boolean;
 				dbType = DbType.Boolean;
 				break;
 				break;
 			case SqlDbType.Char:
 			case SqlDbType.Char:
-				typeName = "char";
+				MetaParameter.TypeName = "char";
 				dbType = DbType.AnsiStringFixedLength;
 				dbType = DbType.AnsiStringFixedLength;
 				break;
 				break;
 			case SqlDbType.DateTime:
 			case SqlDbType.DateTime:
-				typeName = "datetime";
+				MetaParameter.TypeName = "datetime";
 				dbType = DbType.DateTime;
 				dbType = DbType.DateTime;
 				break;
 				break;
 			case SqlDbType.SmallDateTime:
 			case SqlDbType.SmallDateTime:
-				typeName = "smalldatetime";
+				MetaParameter.TypeName = "smalldatetime";
 				dbType = DbType.DateTime;
 				dbType = DbType.DateTime;
 				break;
 				break;
 			case SqlDbType.Decimal:
 			case SqlDbType.Decimal:
-				typeName = "decimal";
+				MetaParameter.TypeName = "decimal";
 				dbType = DbType.Decimal;
 				dbType = DbType.Decimal;
 				break;
 				break;
 			case SqlDbType.Float:
 			case SqlDbType.Float:
-				typeName = "float";
+				MetaParameter.TypeName = "float";
 				dbType = DbType.Double;
 				dbType = DbType.Double;
 				break;
 				break;
 			case SqlDbType.Image:
 			case SqlDbType.Image:
-				typeName = "image";
+				MetaParameter.TypeName = "image";
 				dbType = DbType.Binary;
 				dbType = DbType.Binary;
 				break;
 				break;
 			case SqlDbType.Int:
 			case SqlDbType.Int:
-				typeName = "int";
+				MetaParameter.TypeName = "int";
 				dbType = DbType.Int32;
 				dbType = DbType.Int32;
 				break;
 				break;
 			case SqlDbType.Money:
 			case SqlDbType.Money:
-				typeName = "money";
+				MetaParameter.TypeName = "money";
 				dbType = DbType.Currency;
 				dbType = DbType.Currency;
 				break;
 				break;
 			case SqlDbType.SmallMoney:
 			case SqlDbType.SmallMoney:
-				typeName = "smallmoney";
+				MetaParameter.TypeName = "smallmoney";
 				dbType = DbType.Currency;
 				dbType = DbType.Currency;
 				break;
 				break;
 			case SqlDbType.NChar:
 			case SqlDbType.NChar:
-				typeName = "nchar";
+				MetaParameter.TypeName = "nchar";
 				dbType = DbType.StringFixedLength;
 				dbType = DbType.StringFixedLength;
 				break;
 				break;
 			case SqlDbType.NText:
 			case SqlDbType.NText:
-				typeName = "ntext";
+				MetaParameter.TypeName = "ntext";
 				dbType = DbType.String;
 				dbType = DbType.String;
 				break;
 				break;
 			case SqlDbType.NVarChar:
 			case SqlDbType.NVarChar:
-				typeName = "nvarchar";
+				MetaParameter.TypeName = "nvarchar";
 				dbType = DbType.String;
 				dbType = DbType.String;
 				break;
 				break;
 			case SqlDbType.Real:
 			case SqlDbType.Real:
-				typeName = "real";
+				MetaParameter.TypeName = "real";
 				dbType = DbType.Single;
 				dbType = DbType.Single;
 				break;
 				break;
 			case SqlDbType.SmallInt:
 			case SqlDbType.SmallInt:
-				typeName = "smallint";
+				MetaParameter.TypeName = "smallint";
 				dbType = DbType.Int16;
 				dbType = DbType.Int16;
 				break;
 				break;
 			case SqlDbType.Text:
 			case SqlDbType.Text:
-				typeName = "text";
+				MetaParameter.TypeName = "text";
 				dbType = DbType.AnsiString;
 				dbType = DbType.AnsiString;
 				break;
 				break;
 			case SqlDbType.VarChar:
 			case SqlDbType.VarChar:
-				typeName = "varchar";
+				MetaParameter.TypeName = "varchar";
 				dbType = DbType.AnsiString;
 				dbType = DbType.AnsiString;
 				break;
 				break;
 			case SqlDbType.TinyInt:
 			case SqlDbType.TinyInt:
-				typeName = "tinyint";
+				MetaParameter.TypeName = "tinyint";
 				dbType = DbType.Byte;
 				dbType = DbType.Byte;
 				break;
 				break;
 			case SqlDbType.UniqueIdentifier:
 			case SqlDbType.UniqueIdentifier:
-				typeName = "uniqueidentifier";
+				MetaParameter.TypeName = "uniqueidentifier";
 				dbType = DbType.Guid;
 				dbType = DbType.Guid;
 				break;
 				break;
 			case SqlDbType.Variant:
 			case SqlDbType.Variant:
-				typeName = "sql_variant";
+				MetaParameter.TypeName = "sql_variant";
 				dbType = DbType.Object;
 				dbType = DbType.Object;
 				break;
 				break;
 			default:
 			default:
@@ -625,7 +590,7 @@ namespace System.Data.SqlClient {
 
 
 		public override string ToString() 
 		public override string ToString() 
 		{
 		{
-			return parameterName;
+			return ParameterName;
 		}
 		}
 
 
 		#endregion // Methods
 		#endregion // Methods

+ 11 - 0
mcs/class/System.Data/System.Data.SqlClient/SqlParameterCollection.cs

@@ -10,6 +10,7 @@
 // Copyright (C) Tim Coleman, 2002
 // Copyright (C) Tim Coleman, 2002
 //
 //
 
 
+using Mono.Data.Tds;
 using System;
 using System;
 using System.ComponentModel;
 using System.ComponentModel;
 using System.Data;
 using System.Data;
@@ -23,6 +24,7 @@ namespace System.Data.SqlClient {
 		#region Fields
 		#region Fields
 
 
 		ArrayList list = new ArrayList();
 		ArrayList list = new ArrayList();
+		TdsMetaParameterCollection metaParameters;
 		SqlCommand command;
 		SqlCommand command;
 
 
 		#endregion // Fields
 		#endregion // Fields
@@ -32,6 +34,7 @@ namespace System.Data.SqlClient {
 		internal SqlParameterCollection (SqlCommand command)
 		internal SqlParameterCollection (SqlCommand command)
 		{
 		{
 			this.command = command;
 			this.command = command;
+			metaParameters = new TdsMetaParameterCollection ();
 		}
 		}
 
 
 		#endregion // Constructors
 		#endregion // Constructors
@@ -96,6 +99,10 @@ namespace System.Data.SqlClient {
 		object ICollection.SyncRoot {
 		object ICollection.SyncRoot {
 			get { return list.SyncRoot; }
 			get { return list.SyncRoot; }
 		}
 		}
+
+		internal TdsMetaParameterCollection MetaParameters {
+			get { return metaParameters; }
+		}
 		
 		
 		#endregion // Properties
 		#endregion // Properties
 
 
@@ -116,6 +123,7 @@ namespace System.Data.SqlClient {
 			
 			
 			value.Container = this;
 			value.Container = this;
 			list.Add (value);
 			list.Add (value);
+			metaParameters.Add (value.MetaParameter);
 			return value;
 			return value;
 		}
 		}
 		
 		
@@ -141,6 +149,7 @@ namespace System.Data.SqlClient {
 
 
 		public void Clear()
 		public void Clear()
 		{
 		{
+			metaParameters.Clear ();
 			list.Clear ();
 			list.Clear ();
 		}
 		}
 		
 		
@@ -188,11 +197,13 @@ namespace System.Data.SqlClient {
 
 
 		public void Remove (object value)
 		public void Remove (object value)
 		{
 		{
+			metaParameters.Remove (((SqlParameter) value).MetaParameter);
 			list.Remove (value);
 			list.Remove (value);
 		}
 		}
 
 
 		public void RemoveAt (int index)
 		public void RemoveAt (int index)
 		{
 		{
+			metaParameters.RemoveAt (index);
 			list.RemoveAt (index);
 			list.RemoveAt (index);
 		}
 		}
 
 

+ 3 - 3
mcs/class/System.Data/System.Data.SqlClient/SqlTransaction.cs

@@ -60,7 +60,7 @@ namespace System.Data.SqlClient {
 		{
 		{
 			if (!isOpen)
 			if (!isOpen)
 				throw new InvalidOperationException ("The Transaction was not open.");
 				throw new InvalidOperationException ("The Transaction was not open.");
-			connection.Tds.ExecuteNonQuery ("COMMIT TRANSACTION");
+			connection.Tds.Execute ("COMMIT TRANSACTION");
 			connection.Transaction = null;
 			connection.Transaction = null;
 			isOpen = false;
 			isOpen = false;
 		}		
 		}		
@@ -90,7 +90,7 @@ namespace System.Data.SqlClient {
 		{
 		{
 			if (!isOpen)
 			if (!isOpen)
 				throw new InvalidOperationException ("The Transaction was not open.");
 				throw new InvalidOperationException ("The Transaction was not open.");
-			connection.Tds.ExecuteNonQuery (String.Format ("ROLLBACK TRANSACTION {0}", transactionName));
+			connection.Tds.Execute (String.Format ("ROLLBACK TRANSACTION {0}", transactionName));
 			isOpen = false;
 			isOpen = false;
 		}
 		}
 
 
@@ -98,7 +98,7 @@ namespace System.Data.SqlClient {
 		{
 		{
 			if (!isOpen)
 			if (!isOpen)
 				throw new InvalidOperationException ("The Transaction was not open.");
 				throw new InvalidOperationException ("The Transaction was not open.");
-			connection.Tds.ExecuteNonQuery (String.Format ("SAVE TRANSACTION {0}", savePointName));
+			connection.Tds.Execute (String.Format ("SAVE TRANSACTION {0}", savePointName));
 		}
 		}
 
 
 		#endregion // Methods
 		#endregion // Methods