4 // Part of the Mono class libraries at
5 // mcs/class/System.Data.OracleClient/System.Data.OracleClient
7 // Assembly: System.Data.OracleClient.dll
8 // Namespace: System.Data.OracleClient
11 // Daniel Morgan <danielmorgan@verizon.net>
12 // Tim Coleman <tim@timcoleman.com>
14 // Copyright (C) Daniel Morgan, 2002, 2004-2005
15 // Copyright (C) Tim Coleman , 2003
17 // Licensed under the MIT/X11 License.
21 using System.ComponentModel;
23 using System.Data.OracleClient.Oci;
24 using System.Drawing.Design;
27 namespace System.Data.OracleClient {
28 [Designer ("Microsoft.VSDesigner.Data.VS.OracleCommandDesigner, " + Consts.AssemblyMicrosoft_VSDesigner)]
30 public sealed class OracleCommand : Component, ICloneable, IDbCommand
34 CommandBehavior behavior;
36 CommandType commandType;
37 OracleConnection connection;
38 bool designTimeVisible;
39 OracleParameterCollection parameters;
40 OracleTransaction transaction;
41 UpdateRowSource updatedRowSource;
43 private OciStatementHandle preparedStatement;
44 OciStatementType statementType;
50 public OracleCommand ()
51 : this (String.Empty, null, null)
55 public OracleCommand (string commandText)
56 : this (commandText, null, null)
60 public OracleCommand (string commandText, OracleConnection connection)
61 : this (commandText, connection, null)
65 public OracleCommand (string commandText, OracleConnection connection, OracleTransaction tx)
67 preparedStatement = null;
68 CommandText = commandText;
69 Connection = connection;
71 CommandType = CommandType.Text;
72 UpdatedRowSource = UpdateRowSource.Both;
73 DesignTimeVisible = false;
75 parameters = new OracleParameterCollection (this);
78 #endregion // Constructors
83 [RefreshProperties (RefreshProperties.All)]
84 [Editor ("Microsoft.VSDesigner.Data.Oracle.Design.OracleCommandTextEditor, " + Consts.AssemblyMicrosoft_VSDesigner, typeof(UITypeEditor))]
85 public string CommandText {
86 get { return commandText; }
87 set { commandText = value; }
90 [RefreshProperties (RefreshProperties.All)]
91 [DefaultValue (CommandType.Text)]
92 public CommandType CommandType {
93 get { return commandType; }
95 if (value == CommandType.TableDirect)
96 throw new ArgumentException ("OracleClient provider does not support TableDirect CommandType.");
101 [DefaultValue (null)]
102 [Editor ("Microsoft.VSDesigner.Data.Design.DbConnectionEditor, " + Consts.AssemblyMicrosoft_VSDesigner, typeof(UITypeEditor))]
103 public OracleConnection Connection {
104 get { return connection; }
105 set { connection = value; }
108 [DefaultValue (true)]
111 public bool DesignTimeVisible {
112 get { return designTimeVisible; }
113 set { designTimeVisible = value; }
116 internal OciEnvironmentHandle Environment {
117 get { return Connection.Environment; }
120 internal OciErrorHandle ErrorHandle {
121 get { return Connection.ErrorHandle; }
124 int IDbCommand.CommandTimeout {
129 [Editor ("Microsoft.VSDesigner.Data.Design.DbConnectionEditor, " + Consts.AssemblyMicrosoft_VSDesigner, typeof(UITypeEditor))]
130 [DefaultValue (null)]
131 IDbConnection IDbCommand.Connection {
132 get { return Connection; }
134 if (!(value is OracleConnection))
135 throw new InvalidCastException ("The value was not a valid OracleConnection.");
136 Connection = (OracleConnection) value;
140 IDataParameterCollection IDbCommand.Parameters {
141 get { return Parameters; }
144 IDbTransaction IDbCommand.Transaction {
145 get { return Transaction; }
147 if (!(value is OracleTransaction))
148 throw new ArgumentException ();
149 Transaction = (OracleTransaction) value;
153 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
154 public OracleParameterCollection Parameters {
155 get { return parameters; }
159 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
160 public OracleTransaction Transaction {
161 get { return transaction; }
162 set { transaction = value; }
165 [DefaultValue (UpdateRowSource.Both)]
166 public UpdateRowSource UpdatedRowSource {
167 get { return updatedRowSource; }
168 set { updatedRowSource = value; }
175 private void AssertCommandTextIsSet ()
177 if (CommandText == String.Empty || CommandText == null)
178 throw new InvalidOperationException ("The command text for this Command has not been set.");
181 private void AssertConnectionIsOpen ()
183 if (Connection == null || Connection.State == ConnectionState.Closed)
184 throw new InvalidOperationException ("An open Connection object is required to continue.");
187 private void AssertNoDataReader ()
189 if (Connection.DataReader != null)
190 throw new InvalidOperationException ("There is already an open DataReader associated with this Connection which must be closed first.");
193 private void AssertTransactionMatch ()
195 if (Connection.Transaction != null && Transaction != Connection.Transaction)
196 throw new InvalidOperationException ("Execute requires the Command object to have a Transaction object when the Connection object assigned to the command is in a pending local transaction. The Transaction property of the Command has not been initialized.");
199 private void BindParameters (OciStatementHandle statement)
201 foreach (OracleParameter p in Parameters)
202 p.Bind (statement, Connection);
206 public void Cancel ()
208 throw new NotImplementedException ();
212 public object Clone ()
214 // create a new OracleCommand object with the same properties
216 OracleCommand cmd = new OracleCommand ();
218 cmd.CommandText = this.CommandText;
219 cmd.CommandType = this.CommandType;
221 // FIXME: not sure if I should set the same object here
222 // or get a clone of these too
223 cmd.Connection = this.Connection;
224 cmd.Transaction = this.Transaction;
226 foreach (OracleParameter parm in this.Parameters) {
228 OracleParameter newParm = cmd.CreateParameter ();
230 newParm.DbType = parm.DbType;
231 newParm.Direction = parm.Direction;
232 newParm.IsNullable = parm.IsNullable;
233 newParm.Offset = parm.Offset;
234 newParm.OracleType = parm.OracleType;
235 newParm.ParameterName = parm.ParameterName;
236 newParm.Precision = parm.Precision;
237 newParm.Scale = parm.Scale;
238 newParm.SourceColumn = parm.SourceColumn;
239 newParm.SourceVersion = parm.SourceVersion;
240 newParm.Value = parm.Value;
242 cmd.Parameters.Add (newParm);
245 //cmd.Container = this.Container;
246 cmd.DesignTimeVisible = this.DesignTimeVisible;
247 //cmd.DesignMode = this.DesignMode;
248 cmd.Site = this.Site;
249 //cmd.UpdateRowSource = this.UpdateRowSource;
254 internal void GetOutParameters ()
256 if (Parameters.Count > 0) {
257 foreach (OracleParameter parm in Parameters) {
258 if (parm.Direction != ParameterDirection.Input) {
265 internal void CloseDataReader ()
269 Connection.DataReader = null;
270 if ((behavior & CommandBehavior.CloseConnection) != 0)
274 public OracleParameter CreateParameter ()
276 return new OracleParameter ();
279 internal void DeriveParameters ()
281 if (commandType != CommandType.StoredProcedure)
282 throw new InvalidOperationException (String.Format ("OracleCommandBuilder DeriveParameters only supports CommandType.StoredProcedure, not CommandType.{0}", commandType));
284 //OracleParameterCollection localParameters = new OracleParameterCollection (this);
286 throw new NotImplementedException ();
289 private int ExecuteNonQueryInternal (OciStatementHandle statement, bool useAutoCommit)
291 if (preparedStatement == null)
292 PrepareStatement (statement);
294 bool isNonQuery = IsNonQuery (statement);
296 BindParameters (statement);
297 if (isNonQuery == true)
298 statement.ExecuteNonQuery (useAutoCommit);
300 statement.ExecuteQuery (false);
304 int rowsAffected = statement.GetAttributeInt32 (OciAttributeType.RowCount, ErrorHandle);
309 public int ExecuteNonQuery ()
311 AssertConnectionIsOpen ();
312 AssertTransactionMatch ();
313 AssertCommandTextIsSet ();
314 bool useAutoCommit = false;
316 if (Transaction != null)
317 Transaction.AttachToServiceContext ();
319 useAutoCommit = true;
321 OciStatementHandle statement = GetStatementHandle ();
323 return ExecuteNonQueryInternal (statement, useAutoCommit);
326 SafeDisposeHandle (statement);
330 public int ExecuteOracleNonQuery (out OracleString rowid)
332 AssertConnectionIsOpen ();
333 AssertTransactionMatch ();
334 AssertCommandTextIsSet ();
335 bool useAutoCommit = false;
337 if (Transaction != null)
338 Transaction.AttachToServiceContext ();
340 useAutoCommit = true;
342 OciStatementHandle statement = GetStatementHandle ();
345 int retval = ExecuteNonQueryInternal (statement, useAutoCommit);
347 OciRowIdDescriptor descriptor = (OciRowIdDescriptor) Environment.Allocate (OciHandleType.RowId);
348 descriptor.SetHandle (statement.GetAttributeIntPtr (OciAttributeType.RowId, ErrorHandle));
350 rowid = new OracleString (descriptor.GetRowId (ErrorHandle));
355 SafeDisposeHandle (statement);
360 public object ExecuteOracleScalar ()
362 object output = DBNull.Value;
364 AssertConnectionIsOpen ();
365 AssertTransactionMatch ();
366 AssertCommandTextIsSet ();
368 if (Transaction != null)
369 Transaction.AttachToServiceContext ();
371 OciStatementHandle statement = GetStatementHandle ();
373 if (preparedStatement == null)
374 PrepareStatement (statement);
376 bool isNonQuery = IsNonQuery (statement);
378 BindParameters (statement);
380 if (isNonQuery == true)
381 ExecuteNonQueryInternal (statement, false);
383 statement.ExecuteQuery (false);
385 if (statement.Fetch ()) {
386 OciDefineHandle defineHandle = (OciDefineHandle) statement.Values [0];
387 if (!defineHandle.IsNull)
388 output = defineHandle.GetOracleValue ();
389 switch (defineHandle.DataType) {
390 case OciDataType.Blob:
391 case OciDataType.Clob:
392 ((OracleLob) output).connection = Connection;
402 SafeDisposeHandle (statement);
406 private bool IsNonQuery (OciStatementHandle statementHandle)
\r
408 // assumes Prepare() has been called prior to calling this function
410 OciStatementType statementType = statementHandle.GetStatementType ();
411 if (statementType.Equals (OciStatementType.Select))
417 public OracleDataReader ExecuteReader ()
419 return ExecuteReader (CommandBehavior.Default);
422 public OracleDataReader ExecuteReader (CommandBehavior behavior)
424 AssertConnectionIsOpen ();
425 AssertTransactionMatch ();
426 AssertCommandTextIsSet ();
427 AssertNoDataReader ();
428 bool hasRows = false;
430 this.behavior = behavior;
432 if (Transaction != null)
433 Transaction.AttachToServiceContext ();
435 OciStatementHandle statement = GetStatementHandle ();
436 OracleDataReader rd = null;
439 if (preparedStatement == null)
440 PrepareStatement (statement);
442 preparedStatement = null; // OracleDataReader releases the statement handle
444 bool isNonQuery = IsNonQuery (statement);
446 BindParameters (statement);
449 ExecuteNonQueryInternal (statement, false);
451 if ((behavior & CommandBehavior.SchemaOnly) != 0)
452 statement.ExecuteQuery (true);
454 hasRows = statement.ExecuteQuery (false);
457 rd = new OracleDataReader (this, statement, hasRows, behavior);
460 if (statement != null && rd == null)
467 public object ExecuteScalar ()
469 object output = DBNull.Value;
471 AssertConnectionIsOpen ();
472 AssertTransactionMatch ();
473 AssertCommandTextIsSet ();
475 if (Transaction != null)
476 Transaction.AttachToServiceContext ();
478 OciStatementHandle statement = GetStatementHandle ();
480 if (preparedStatement == null)
481 PrepareStatement (statement);
483 bool isNonQuery = IsNonQuery (statement);
485 BindParameters (statement);
487 if (isNonQuery == true)
488 ExecuteNonQueryInternal (statement, false);
490 statement.ExecuteQuery (false);
492 if (statement.Fetch ()) {
493 OciDefineHandle defineHandle = (OciDefineHandle) statement.Values [0];
494 if (defineHandle.IsNull)
495 output = DBNull.Value;
497 switch (defineHandle.DataType) {
498 case OciDataType.Blob:
499 case OciDataType.Clob:
500 OracleLob lob = (OracleLob) defineHandle.GetValue ();
501 lob.connection = Connection;
506 output = defineHandle.GetValue ();
512 output = DBNull.Value;
517 SafeDisposeHandle (statement);
523 private OciStatementHandle GetStatementHandle ()
525 AssertConnectionIsOpen ();
526 if (preparedStatement != null)
527 return preparedStatement;
529 OciStatementHandle h = (OciStatementHandle) Connection.Environment.Allocate (OciHandleType.Statement);
530 h.ErrorHandle = Connection.ErrorHandle;
531 h.Service = Connection.ServiceContext;
536 private void SafeDisposeHandle (OciStatementHandle h)
538 if (h != null && h != preparedStatement)
542 IDbDataParameter IDbCommand.CreateParameter ()
544 return CreateParameter ();
547 IDataReader IDbCommand.ExecuteReader ()
549 return ExecuteReader ();
552 IDataReader IDbCommand.ExecuteReader (CommandBehavior behavior)
554 return ExecuteReader (behavior);
557 void PrepareStatement (OciStatementHandle statement)
559 if (commandType == CommandType.StoredProcedure) {
560 StringBuilder sb = new StringBuilder ();
561 if (Parameters.Count > 0)
\r
562 foreach (OracleParameter parm in Parameters) {
\r
565 sb.Append (":" + parm.ParameterName);
\r
568 string sql = "call " + commandText + "(" + sb.ToString() + ")";
\r
569 statement.Prepare (sql);
572 statement.Prepare (commandText);
575 public void Prepare ()
577 AssertConnectionIsOpen ();
578 OciStatementHandle statement = GetStatementHandle ();
579 PrepareStatement (statement);
580 preparedStatement = statement;
583 #endregion // Methods