Kaynağa Gözat

2005-08-08 Sureshkumar T <[email protected]>

	* OdbcDataReader.cs: Implemented Dispose pattern. Cache
	schematable for same result set. don't free command's statements
	if the command is prepared.

	* OdbcCommand.cs:
	- Implemented Dispose pattern
	- Streamlined the allocation and de-allocation of statement
	handles.


svn path=/trunk/mcs/; revision=48120
Sureshkumar T 20 yıl önce
ebeveyn
işleme
807abd8d52

+ 11 - 2
mcs/class/System.Data/System.Data.Odbc/ChangeLog

@@ -1,13 +1,22 @@
 2005-08-08  Sureshkumar T  <[email protected]>
 
+	* OdbcDataReader.cs: Implemented Dispose pattern. Cache
+	schematable for same result set. don't free command's statements
+	if the command is prepared.
+
 	* OdbcConnection.cs: Open (): set disposed to false so that close
 	will be called in Dispose.
 
-	* OdbcCommand.cs: Prepare (): Split SQLPrepare and SQLBind so that
+	* OdbcCommand.cs:
+	- Prepare (): Split SQLPrepare and SQLBind so that
 	already prepared statements can be reused with new parameter
-	values. ExecSQL (): create new statement handle, if not prepared
+	values.
+	- ExecSQL (): create new statement handle, if not prepared
 	and there are no parameters. if there are parameters, prepare and
 	use.
+	- Implemented Dispose pattern
+	- Streamlined the allocation and de-allocation of statement
+	handles.
 
 2005-08-05  Sureshkumar T  <[email protected]>
 

+ 60 - 17
mcs/class/System.Data/System.Data.Odbc/OdbcCommand.cs

@@ -68,8 +68,9 @@ namespace System.Data.Odbc
 
 		bool designTimeVisible;
 		bool prepared=false;
-		OdbcDataReader dataReader;
-		IntPtr hstmt;
+		IntPtr hstmt = IntPtr.Zero;
+
+		bool disposed = false;
 		
 		#endregion // Fields
 
@@ -84,7 +85,6 @@ namespace System.Data.Odbc
 			_parameters = new OdbcParameterCollection ();
 			Transaction = null;
 			designTimeVisible = false;
-			dataReader = null;
 #if ONLY_1_1
 			updateRowSource = UpdateRowSource.Both;
 #endif // ONLY_1_1
@@ -367,19 +367,59 @@ namespace System.Data.Odbc
 #endif // ONLY_1_1
 
 		
-		[MonoTODO]
 		protected override void Dispose (bool disposing)
 		{
+			if (disposed)
+				return;
+			
+			FreeStatement (); // free handles
+			Connection = null;
+			Transaction = null;
+			disposed = true;
+		}
+
+		~OdbcCommand ()
+		{
+			Dispose (false);
+		}
+
+		private IntPtr ReAllocStatment ()
+		{
+			OdbcReturn ret;
+
+			if (hstmt != IntPtr.Zero)
+				FreeStatement ();
+
+			ret=libodbc.SQLAllocHandle(OdbcHandleType.Stmt, Connection.hDbc, ref hstmt);
+			if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+				throw new OdbcException(new OdbcError("SQLAllocHandle",OdbcHandleType.Dbc,Connection.hDbc));
+			disposed = false;
+			return hstmt;
+		}
+
+		private void FreeStatement ()
+		{
+			if (hstmt == IntPtr.Zero)
+				return;
+			
+			// free previously allocated handle.
+			OdbcReturn ret = libodbc.SQLFreeStmt (hstmt, libodbc.SQLFreeStmtOptions.Close);
+			if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+				throw new OdbcException(new OdbcError("SQLCloseCursor",OdbcHandleType.Stmt,hstmt));
+			
+			ret = libodbc.SQLFreeHandle( (ushort) OdbcHandleType.Stmt, hstmt);
+			if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
+				throw new OdbcException(new OdbcError("SQLFreeHandle",OdbcHandleType.Stmt,hstmt));
+			hstmt = IntPtr.Zero;
 		}
 		
 		private void ExecSQL(string sql)
 		{
 			OdbcReturn ret;
 			if (! prepared && Parameters.Count <= 0) {
-				ret=libodbc.SQLAllocHandle(OdbcHandleType.Stmt, Connection.hDbc, ref hstmt);
-				if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
-					throw new OdbcException(new OdbcError("SQLAllocHandle",OdbcHandleType.Dbc,Connection.hDbc));
 
+				ReAllocStatment ();
+				
 				ret=libodbc.SQLExecDirect(hstmt, sql, sql.Length);
 				if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
 					throw new OdbcException(new OdbcError("SQLExecDirect",OdbcHandleType.Stmt,hstmt));
@@ -395,6 +435,12 @@ namespace System.Data.Odbc
 				throw new OdbcException(new OdbcError("SQLExecute",OdbcHandleType.Stmt,hstmt));
 		}
 
+		internal void FreeIfNotPrepared ()
+		{
+			if (! prepared)
+				FreeStatement ();
+		}
+
 		public
 #if NET_2_0
                 override
@@ -429,11 +475,9 @@ namespace System.Data.Odbc
                         else
 				records = -1;
 
-			if (freeHandle && !prepared) {
-				OdbcReturn ret = libodbc.SQLFreeHandle( (ushort) OdbcHandleType.Stmt, hstmt);
-				if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
-					throw new OdbcException(new OdbcError("SQLFreeHandle",OdbcHandleType.Stmt,hstmt));
-			}
+			if (freeHandle && !prepared)
+				FreeStatement ();
+			
 			return records;
 		}
 
@@ -443,10 +487,9 @@ namespace System.Data.Odbc
 #endif // NET_2_0
                 void Prepare()
 		{
-			OdbcReturn ret=libodbc.SQLAllocHandle(OdbcHandleType.Stmt, Connection.hDbc, ref hstmt);
-			if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
-				throw new OdbcException(new OdbcError("SQLAllocHandle",OdbcHandleType.Dbc,Connection.hDbc));
-
+			ReAllocStatment ();
+			
+			OdbcReturn ret;
 			ret=libodbc.SQLPrepare(hstmt, CommandText, CommandText.Length);
 			if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
 				throw new OdbcException(new OdbcError("SQLPrepare",OdbcHandleType.Stmt,hstmt));
@@ -493,7 +536,7 @@ namespace System.Data.Odbc
                 OdbcDataReader ExecuteReader (CommandBehavior behavior)
 		{
 			int recordsAffected = ExecuteNonQuery(false);
-			dataReader=new OdbcDataReader(this, behavior, recordsAffected);
+			OdbcDataReader dataReader=new OdbcDataReader(this, behavior, recordsAffected);
 			return dataReader;
 		}
 

+ 38 - 16
mcs/class/System.Data/System.Data.Odbc/OdbcDataReader.cs

@@ -58,6 +58,8 @@ namespace System.Data.Odbc
 		private OdbcColumn[] cols;
 		private IntPtr hstmt;
 		private int _recordsAffected = -1;
+		bool disposed = false;
+		private DataTable _dataTableSchema;
 #if ONLY_1_1
 		private CommandBehavior behavior;
 #endif // ONLY_1_1
@@ -254,25 +256,19 @@ namespace System.Data.Odbc
                 void Close ()
 		{
 			// FIXME : have to implement output parameter binding
-			OdbcReturn ret = libodbc.SQLFreeStmt (hstmt, libodbc.SQLFreeStmtOptions.Close);
-			if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
-				throw new OdbcException(new OdbcError("SQLCloseCursor",OdbcHandleType.Stmt,hstmt));
-	
 			open = false;
 			currentRow = -1;
 
-			ret = libodbc.SQLFreeHandle( (ushort) OdbcHandleType.Stmt, hstmt);
-				if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) 
-					throw new OdbcException(new OdbcError("SQLFreeHandle",OdbcHandleType.Stmt,hstmt));
+			this.command.FreeIfNotPrepared ();
 
-				if ((this.CommandBehavior & CommandBehavior.CloseConnection)==CommandBehavior.CloseConnection)
-					this.command.Connection.Close();
+			if ((this.CommandBehavior & CommandBehavior.CloseConnection)==CommandBehavior.CloseConnection) {
+				this.command.Connection.Close();
+			}
 		}
 
 		~OdbcDataReader ()
 		{
-			if (open)
-				Close ();
+			this.Dispose (false);
 		}
 
 		public 
@@ -511,9 +507,10 @@ namespace System.Data.Odbc
                         // * Map OdbcType to System.Type and assign to DataType.
                         //   This will eliminate the need for IsStringType in
                         //   OdbcColumn.
-                        // * Cache this DataTable so that it is not contacting 
-                        //   datasource everytime for the same result set.
 
+			if (_dataTableSchema != null)
+				return _dataTableSchema;
+			
 			DataTable dataTableSchema = null;
 			// Only Results from SQL SELECT Queries 
 			// get a DataTable for schema of the result
@@ -612,7 +609,7 @@ namespace System.Data.Odbc
 				}
                                 dataTableSchema.AcceptChanges();
 			}
-                        return dataTableSchema;
+                        return (_dataTableSchema = dataTableSchema);
 		}
 
 		public 
@@ -795,17 +792,41 @@ namespace System.Data.Odbc
 			throw new NotImplementedException ();
 		}
 
-		[MonoTODO]
+#if ONLY_1_1
 		void IDisposable.Dispose ()
 		{
+			Dispose (true);
+			GC.SuppressFinalize (this);
 		}
-
+#else
+		public override void Dispose ()
+		{
+			Dispose (true);
+			GC.SuppressFinalize (this);
+		}
+#endif
                 IEnumerator IEnumerable.GetEnumerator ()
 		{
 			return new DbEnumerator (this);
 		}
 #endif // ONLY_1_1
 
+		private void Dispose (bool disposing)
+		{
+			if (disposed)
+				return;
+
+			if (disposing) {
+				// dispose managed resources
+				Close ();
+			}
+
+			command = null;
+			cols = null;
+			_dataTableSchema = null;
+			disposed = true;
+		}
+
 		public
 #if NET_2_0
                 override
@@ -830,6 +851,7 @@ namespace System.Data.Odbc
 				short colcount = 0;
 				libodbc.SQLNumResultCols (hstmt, ref colcount);
 				cols = new OdbcColumn [colcount];
+				_dataTableSchema = null; // force fresh creation
 				GetSchemaTable ();
 			}	
 			return (ret==OdbcReturn.Success);