2 // System.Data.SqlClient.SqlCommand.cs
5 // Rodrigo Moya (rodrigo@ximian.com)
6 // Daniel Morgan (danmorg@sc.rr.com)
7 // Tim Coleman (tim@timcoleman.com)
8 // Diego Caravana (diego@toth.it)
10 // (C) Ximian, Inc 2002 http://www.ximian.com/
11 // (C) Daniel Morgan, 2002
12 // Copyright (C) Tim Coleman, 2002
16 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
18 // Permission is hereby granted, free of charge, to any person obtaining
19 // a copy of this software and associated documentation files (the
20 // "Software"), to deal in the Software without restriction, including
21 // without limitation the rights to use, copy, modify, merge, publish,
22 // distribute, sublicense, and/or sell copies of the Software, and to
23 // permit persons to whom the Software is furnished to do so, subject to
24 // the following conditions:
26 // The above copyright notice and this permission notice shall be
27 // included in all copies or substantial portions of the Software.
29 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39 using Mono
.Data
.Tds
.Protocol
;
42 using System
.Collections
;
43 using System
.Collections
.Specialized
;
44 using System
.ComponentModel
;
46 using System
.Data
.Common
;
48 using System
.Data
.Sql
;
50 using System
.Runtime
.InteropServices
;
54 namespace System
.Data
.SqlClient
{
55 [DesignerAttribute ("Microsoft.VSDesigner.Data.VS.SqlCommandDesigner, "+ Consts
.AssemblyMicrosoft_VSDesigner
, "System.ComponentModel.Design.IDesigner")]
56 [ToolboxItemAttribute ("System.Drawing.Design.ToolboxItem, "+ Consts
.AssemblySystem_Drawing
)]
58 [DefaultEventAttribute ("RecordsAffected")]
59 public sealed class SqlCommand
: DbCommand
, IDbCommand
, ICloneable
61 public sealed class SqlCommand
: Component
, IDbCommand
, ICloneable
66 const int DEFAULT_COMMAND_TIMEOUT
= 30;
69 bool designTimeVisible
;
71 CommandType commandType
;
72 SqlConnection connection
;
73 SqlTransaction transaction
;
74 UpdateRowSource updatedRowSource
;
75 CommandBehavior behavior
= CommandBehavior
.Default
;
76 SqlParameterCollection parameters
;
77 string preparedStatement
;
80 SqlNotificationRequest notification
;
81 bool notificationAutoEnlist
;
89 : this (String
.Empty
, null, null)
93 public SqlCommand (string cmdText
)
94 : this (cmdText
, null, null)
98 public SqlCommand (string cmdText
, SqlConnection connection
)
99 : this (cmdText
, connection
, null)
103 public SqlCommand (string cmdText
, SqlConnection connection
, SqlTransaction transaction
)
105 this.commandText
= cmdText
;
106 this.connection
= connection
;
107 this.transaction
= transaction
;
108 this.commandType
= CommandType
.Text
;
109 this.updatedRowSource
= UpdateRowSource
.Both
;
111 this.commandTimeout
= DEFAULT_COMMAND_TIMEOUT
;
113 notificationAutoEnlist
= true;
115 designTimeVisible
= true;
116 parameters
= new SqlParameterCollection (this);
119 private SqlCommand(string commandText
, SqlConnection connection
, SqlTransaction transaction
, CommandType commandType
, UpdateRowSource updatedRowSource
, bool designTimeVisible
, int commandTimeout
, SqlParameterCollection parameters
)
121 this.commandText
= commandText
;
122 this.connection
= connection
;
123 this.transaction
= transaction
;
124 this.commandType
= commandType
;
125 this.updatedRowSource
= updatedRowSource
;
126 this.designTimeVisible
= designTimeVisible
;
127 this.commandTimeout
= commandTimeout
;
128 this.parameters
= new SqlParameterCollection(this);
129 for (int i
= 0;i
< parameters
.Count
;i
++)
130 this.parameters
.Add(((ICloneable
)parameters
[i
]).Clone());
133 #endregion // Constructors
137 internal CommandBehavior CommandBehavior
{
138 get { return behavior; }
142 [DataSysDescription ("Command text to execute.")]
145 [EditorAttribute ("Microsoft.VSDesigner.Data.SQL.Design.SqlCommandTextEditor, "+ Consts
.AssemblyMicrosoft_VSDesigner
, "System.Drawing.Design.UITypeEditor, "+ Consts
.AssemblySystem_Drawing
)]
146 [RefreshProperties (RefreshProperties
.All
)]
153 if (commandText
== null)
158 if (value != commandText
&& preparedStatement
!= null)
165 [DataSysDescription ("Time to wait for command to execute.")]
166 [DefaultValue (DEFAULT_COMMAND_TIMEOUT
)]
173 get { return commandTimeout; }
177 throw new ArgumentException ("The property value assigned is less than 0.",
180 throw new ArgumentException ("The property value assigned is less than 0.");
182 commandTimeout
= value;
187 [DataSysDescription ("How to interpret the CommandText.")]
189 [DefaultValue (CommandType
.Text
)]
190 [RefreshProperties (RefreshProperties
.All
)]
195 CommandType CommandType
{
196 get { return commandType; }
198 if (value == CommandType
.TableDirect
)
200 throw new ArgumentOutOfRangeException ("CommandType.TableDirect is not supported " +
201 "by the Mono SqlClient Data Provider.");
203 throw new ArgumentException ("CommandType.TableDirect is not supported by the Mono SqlClient Data Provider.");
206 ExceptionHelper
.CheckEnumValue (typeof (CommandType
), value);
211 [DefaultValue (null)]
213 [DataSysDescription ("Connection used by the command.")]
215 [EditorAttribute ("Microsoft.VSDesigner.Data.Design.DbConnectionEditor, "+ Consts
.AssemblyMicrosoft_VSDesigner
, "System.Drawing.Design.UITypeEditor, "+ Consts
.AssemblySystem_Drawing
)]
220 SqlConnection Connection
{
221 get { return connection; }
225 if (connection
!= null && connection
.DataReader
!= null)
226 throw new InvalidOperationException ("The connection is busy fetching data.");
233 [DefaultValue (true)]
236 [EditorBrowsable (EditorBrowsableState
.Never
)]
242 bool DesignTimeVisible
{
243 get { return designTimeVisible; }
244 set { designTimeVisible = value; }
248 [DataSysDescription ("The parameters collection.")]
250 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Content
)]
255 SqlParameterCollection Parameters
{
256 get { return parameters; }
260 get { return Connection.Tds; }
264 IDbConnection IDbCommand
.Connection
{
265 get { return Connection; }
267 if (!(value == null || value is SqlConnection
))
268 throw new InvalidCastException ("The value was not a valid SqlConnection.");
269 Connection
= (SqlConnection
) value;
273 IDataParameterCollection IDbCommand
.Parameters
{
274 get { return Parameters; }
277 IDbTransaction IDbCommand
.Transaction
{
278 get { return Transaction; }
280 if (!(value == null || value is SqlTransaction
))
281 throw new ArgumentException ();
282 Transaction
= (SqlTransaction
) value;
289 [DataSysDescription ("The transaction used by the command.")]
291 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
292 public new SqlTransaction Transaction
{
294 if (transaction
!= null && !transaction
.IsOpen
)
301 if (connection
!= null && connection
.DataReader
!= null)
302 throw new InvalidOperationException ("The connection is busy fetching data.");
309 [DataSysDescription ("When used by a DataAdapter.Update, how command results are applied to the current DataRow.")]
311 [DefaultValue (UpdateRowSource
.Both
)]
316 UpdateRowSource UpdatedRowSource
{
317 get { return updatedRowSource; }
319 ExceptionHelper
.CheckEnumValue (typeof (UpdateRowSource
), value);
320 updatedRowSource
= value;
326 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
327 public SqlNotificationRequest Notification
{
328 get { return notification; }
329 set { notification = value; }
332 [DefaultValue (true)]
333 public bool NotificationAutoEnlist
{
334 get { return notificationAutoEnlist; }
335 set { notificationAutoEnlist = value; }
348 if (Connection
== null || Connection
.Tds
== null)
350 Connection
.Tds
.Cancel ();
354 public SqlCommand
Clone ()
356 return new SqlCommand (commandText
, connection
, transaction
, commandType
, updatedRowSource
, designTimeVisible
, commandTimeout
, parameters
);
360 internal void CloseDataReader ()
362 if (Connection
!= null) {
363 Connection
.DataReader
= null;
365 if ((behavior
& CommandBehavior
.CloseConnection
) != 0)
369 Tds
.SequentialAccess
= false;
372 // Reset the behavior
373 behavior
= CommandBehavior
.Default
;
376 public new SqlParameter
CreateParameter ()
378 return new SqlParameter ();
381 private string EscapeProcName (string name
, bool schema
)
384 string tmpProcName
= name
.Trim ();
385 int procNameLen
= tmpProcName
.Length
;
386 char[] brkts
= new char [] {'[', ']'}
;
387 bool foundMatching
= false;
388 int start
= 0, count
= procNameLen
;
389 int sindex
= -1, eindex
= -1;
391 // We try to match most of the "brackets" combination here, however
392 // there could be other combinations that may generate a different type
393 // of exception in MS.NET
395 if (procNameLen
> 1) {
396 if ((sindex
= tmpProcName
.IndexOf ('[')) <= 0)
397 foundMatching
= true;
399 foundMatching
= false;
401 if (foundMatching
== true && sindex
> -1) {
402 eindex
= tmpProcName
.IndexOf (']');
403 if (sindex
> eindex
&& eindex
!= -1) {
404 foundMatching
= false;
405 } else if (eindex
== procNameLen
-1) {
406 if (tmpProcName
.IndexOfAny (brkts
, 1, procNameLen
-2) != -1) {
407 foundMatching
= false;
410 count
= procNameLen
- 2;
412 } else if (eindex
== -1 && schema
) {
413 foundMatching
= true;
415 foundMatching
= false;
420 procName
= tmpProcName
.Substring (start
, count
);
422 throw new ArgumentException (String
.Format ("SqlCommand.CommandText property value is an invalid multipart name {0}, incorrect usage of quotes", CommandText
));
424 procName
= tmpProcName
;
429 internal void DeriveParameters ()
431 if (commandType
!= CommandType
.StoredProcedure
)
432 throw new InvalidOperationException (String
.Format ("SqlCommand DeriveParameters only supports CommandType.StoredProcedure, not CommandType.{0}", commandType
));
433 ValidateCommand ("DeriveParameters", false);
435 string procName
= CommandText
;
436 string schemaName
= String
.Empty
;
437 int dotPosition
= procName
.IndexOf ('.');
438 if (dotPosition
>= 0) {
439 schemaName
= procName
.Substring (0, dotPosition
);
440 procName
= procName
.Substring (dotPosition
+ 1);
443 procName
= EscapeProcName (procName
, false);
444 schemaName
= EscapeProcName (schemaName
, true);
446 SqlParameterCollection localParameters
= new SqlParameterCollection (this);
447 localParameters
.Add ("@procedure_name", SqlDbType
.NVarChar
, procName
.Length
).Value
= procName
;
448 if (schemaName
.Length
> 0)
449 localParameters
.Add ("@procedure_schema", SqlDbType
.NVarChar
, schemaName
.Length
).Value
= schemaName
;
451 string sql
= "sp_procedure_params_rowset";
454 Connection
.Tds
.ExecProc (sql
, localParameters
.MetaParameters
, 0, true);
455 } catch (TdsTimeoutException ex
) {
456 Connection
.Tds
.Reset ();
457 throw SqlException
.FromTdsInternalException ((TdsInternalException
) ex
);
458 } catch (TdsInternalException ex
) {
460 throw SqlException
.FromTdsInternalException ((TdsInternalException
) ex
);
463 SqlDataReader reader
= new SqlDataReader (this);
465 object[] dbValues
= new object[reader
.FieldCount
];
467 while (reader
.Read ()) {
468 reader
.GetValues (dbValues
);
469 parameters
.Add (new SqlParameter (dbValues
));
473 if (parameters
.Count
== 0)
474 throw new InvalidOperationException ("Stored procedure '" + procName
+ "' does not exist.");
477 private void Execute (bool wantResults
)
480 Connection
.Tds
.RecordsAffected
= -1;
481 TdsMetaParameterCollection parms
= Parameters
.MetaParameters
;
482 foreach (TdsMetaParameter param
in parms
) {
483 param
.Validate (index
++);
486 if (preparedStatement
== null) {
487 bool schemaOnly
= ((behavior
& CommandBehavior
.SchemaOnly
) > 0);
488 bool keyInfo
= ((behavior
& CommandBehavior
.KeyInfo
) > 0);
490 StringBuilder sql1
= new StringBuilder ();
491 StringBuilder sql2
= new StringBuilder ();
493 if (schemaOnly
|| keyInfo
)
494 sql1
.Append ("SET FMTONLY OFF;");
496 sql1
.Append ("SET NO_BROWSETABLE ON;");
497 sql2
.Append ("SET NO_BROWSETABLE OFF;");
500 sql1
.Append ("SET FMTONLY ON;");
501 sql2
.Append ("SET FMTONLY OFF;");
504 switch (CommandType
) {
505 case CommandType
.StoredProcedure
:
507 if (keyInfo
|| schemaOnly
)
508 Connection
.Tds
.Execute (sql1
.ToString ());
509 Connection
.Tds
.ExecProc (CommandText
, parms
, CommandTimeout
, wantResults
);
510 if (keyInfo
|| schemaOnly
)
511 Connection
.Tds
.Execute (sql2
.ToString ());
512 } catch (TdsTimeoutException ex
) {
513 // If it is a timeout exception there can be many reasons:
514 // 1) Network is down/server is down/not reachable
515 // 2) Somebody has an exclusive lock on Table/DB
516 // In any of these cases, don't close the connection. Let the user do it
517 Connection
.Tds
.Reset ();
518 throw SqlException
.FromTdsInternalException ((TdsInternalException
) ex
);
519 } catch (TdsInternalException ex
) {
521 throw SqlException
.FromTdsInternalException ((TdsInternalException
) ex
);
524 case CommandType
.Text
:
526 if (sql2
.Length
> 0) {
527 sql
= String
.Format ("{0}{1};{2}", sql1
.ToString (), CommandText
, sql2
.ToString ());
529 sql
= String
.Format ("{0}{1}", sql1
.ToString (), CommandText
);
532 Connection
.Tds
.Execute (sql
, parms
, CommandTimeout
, wantResults
);
533 } catch (TdsTimeoutException ex
) {
534 Connection
.Tds
.Reset ();
535 throw SqlException
.FromTdsInternalException ((TdsInternalException
) ex
);
536 } catch (TdsInternalException ex
) {
538 throw SqlException
.FromTdsInternalException ((TdsInternalException
) ex
);
545 Connection
.Tds
.ExecPrepared (preparedStatement
, parms
, CommandTimeout
, wantResults
);
546 } catch (TdsTimeoutException ex
) {
547 Connection
.Tds
.Reset ();
548 throw SqlException
.FromTdsInternalException ((TdsInternalException
) ex
);
549 } catch (TdsInternalException ex
) {
551 throw SqlException
.FromTdsInternalException ((TdsInternalException
) ex
);
560 int ExecuteNonQuery ()
562 ValidateCommand ("ExecuteNonQuery", false);
564 behavior
= CommandBehavior
.Default
;
568 result
= Connection
.Tds
.RecordsAffected
;
569 } catch (TdsTimeoutException e
) {
570 Connection
.Tds
.Reset ();
571 throw SqlException
.FromTdsInternalException ((TdsInternalException
) e
);
574 GetOutputParameters ();
578 public new SqlDataReader
ExecuteReader ()
580 return ExecuteReader (CommandBehavior
.Default
);
583 public new SqlDataReader
ExecuteReader (CommandBehavior behavior
)
585 ValidateCommand ("ExecuteReader", false);
586 if ((behavior
& CommandBehavior
.SingleRow
) != 0)
587 behavior
|= CommandBehavior
.SingleResult
;
588 this.behavior
= behavior
;
589 if ((behavior
& CommandBehavior
.SequentialAccess
) != 0)
590 Tds
.SequentialAccess
= true;
593 Connection
.DataReader
= new SqlDataReader (this);
594 return Connection
.DataReader
;
596 if ((behavior
& CommandBehavior
.CloseConnection
) != 0)
606 object ExecuteScalar ()
609 object result
= null;
611 ValidateCommand ("ExecuteScalar", false);
613 ValidateCommand ("ExecuteReader", false);
615 behavior
= CommandBehavior
.Default
;
619 if (Connection
.Tds
.NextResult () && Connection
.Tds
.NextRow ())
620 result
= Connection
.Tds
.ColumnValues
[0];
622 if (commandType
== CommandType
.StoredProcedure
) {
623 Connection
.Tds
.SkipToEnd ();
624 GetOutputParameters ();
626 } catch (TdsTimeoutException ex
) {
627 Connection
.Tds
.Reset ();
628 throw SqlException
.FromTdsInternalException ((TdsInternalException
) ex
);
629 } catch (TdsInternalException ex
) {
631 throw SqlException
.FromTdsInternalException ((TdsInternalException
) ex
);
640 public XmlReader
ExecuteXmlReader ()
642 ValidateCommand ("ExecuteXmlReader", false);
643 behavior
= CommandBehavior
.Default
;
646 } catch (TdsTimeoutException e
) {
647 Connection
.Tds
.Reset ();
648 throw SqlException
.FromTdsInternalException ((TdsInternalException
) e
);
651 SqlDataReader dataReader
= new SqlDataReader (this);
652 SqlXmlTextReader textReader
= new SqlXmlTextReader (dataReader
);
653 XmlReader xmlReader
= new XmlTextReader (textReader
);
657 internal void GetOutputParameters ()
659 IList list
= Connection
.Tds
.OutputParameters
;
661 if (list
!= null && list
.Count
> 0) {
664 foreach (SqlParameter parameter
in parameters
) {
665 if (parameter
.Direction
!= ParameterDirection
.Input
&&
666 parameter
.Direction
!= ParameterDirection
.ReturnValue
) {
667 parameter
.Value
= list
[index
];
670 if (index
>= list
.Count
)
676 object ICloneable
.Clone ()
678 return new SqlCommand (commandText
, connection
, transaction
, commandType
, updatedRowSource
, designTimeVisible
, commandTimeout
, parameters
);
683 IDbDataParameter IDbCommand
.CreateParameter ()
685 return CreateParameter ();
688 IDataReader IDbCommand
.ExecuteReader ()
690 return ExecuteReader ();
693 IDataReader IDbCommand
.ExecuteReader (CommandBehavior behavior
)
695 return ExecuteReader (behavior
);
700 protected override void Dispose (bool disposing
)
702 if (disposed
) return;
706 base.Dispose (disposing
);
718 if (Connection
== null)
719 throw new NullReferenceException ();
722 if (CommandType
== CommandType
.StoredProcedure
|| CommandType
== CommandType
.Text
&& Parameters
.Count
== 0)
725 ValidateCommand ("Prepare", false);
728 foreach (SqlParameter param
in Parameters
)
729 param
.CheckIfInitialized ();
730 } catch (Exception e
) {
731 throw new InvalidOperationException ("SqlCommand.Prepare requires " + e
.Message
);
734 preparedStatement
= Connection
.Tds
.Prepare (CommandText
, Parameters
.MetaParameters
);
737 public void ResetCommandTimeout ()
739 commandTimeout
= DEFAULT_COMMAND_TIMEOUT
;
742 private void Unprepare ()
744 Connection
.Tds
.Unprepare (preparedStatement
);
745 preparedStatement
= null;
748 private void ValidateCommand (string method
, bool async)
750 if (Connection
== null)
751 throw new InvalidOperationException (String
.Format ("{0}: A Connection object is required to continue.", method
));
752 if (Transaction
== null && Connection
.Transaction
!= null)
753 throw new InvalidOperationException (String
.Format (
754 "{0} requires a transaction if the command's connection is in a pending transaction.",
760 if (Transaction
!= null && Transaction
.Connection
!= Connection
)
761 throw new InvalidOperationException ("The connection does not have the same transaction as the command.");
762 if (Connection
.State
!= ConnectionState
.Open
)
763 throw new InvalidOperationException (String
.Format ("{0} requires an open connection to continue. This connection is closed.", method
));
764 if (CommandText
.Length
== 0)
765 throw new InvalidOperationException (String
.Format ("{0}: CommandText has not been set for this Command.", method
));
766 if (Connection
.DataReader
!= null)
767 throw new InvalidOperationException ("There is already an open DataReader associated with this Connection which must be closed first.");
768 if (Connection
.XmlReader
!= null)
769 throw new InvalidOperationException ("There is already an open XmlReader associated with this Connection which must be closed first.");
771 if (async && !Connection
.AsyncProcessing
)
772 throw new InvalidOperationException ("This Connection object is not " +
773 "in Asynchronous mode. Use 'Asynchronous" +
774 " Processing = true' to set it.");
779 protected override DbParameter
CreateDbParameter ()
781 return CreateParameter ();
784 protected override DbDataReader
ExecuteDbDataReader (CommandBehavior behavior
)
786 return ExecuteReader (behavior
);
789 protected override DbConnection DbConnection
{
790 get { return Connection; }
791 set { Connection = (SqlConnection) value; }
794 protected override DbParameterCollection DbParameterCollection
{
795 get { return Parameters; }
798 protected override DbTransaction DbTransaction
{
799 get { return Transaction; }
800 set { Transaction = (SqlTransaction) value; }
804 #endregion // Methods
807 #region Asynchronous Methods
809 internal IAsyncResult
BeginExecuteInternal (CommandBehavior behavior
,
811 AsyncCallback callback
,
814 IAsyncResult ar
= null;
815 Connection
.Tds
.RecordsAffected
= -1;
816 TdsMetaParameterCollection parms
= Parameters
.MetaParameters
;
817 if (preparedStatement
== null) {
818 bool schemaOnly
= ((behavior
& CommandBehavior
.SchemaOnly
) > 0);
819 bool keyInfo
= ((behavior
& CommandBehavior
.KeyInfo
) > 0);
821 StringBuilder sql1
= new StringBuilder ();
822 StringBuilder sql2
= new StringBuilder ();
824 if (schemaOnly
|| keyInfo
)
825 sql1
.Append ("SET FMTONLY OFF;");
827 sql1
.Append ("SET NO_BROWSETABLE ON;");
828 sql2
.Append ("SET NO_BROWSETABLE OFF;");
831 sql1
.Append ("SET FMTONLY ON;");
832 sql2
.Append ("SET FMTONLY OFF;");
834 switch (CommandType
) {
835 case CommandType
.StoredProcedure
:
838 if (keyInfo
|| schemaOnly
)
839 prolog
= sql1
.ToString ();
840 if (keyInfo
|| schemaOnly
)
841 epilog
= sql2
.ToString ();
843 Connection
.Tds
.BeginExecuteProcedure (prolog
,
850 } catch (TdsTimeoutException ex
) {
851 Connection
.Tds
.Reset ();
852 throw SqlException
.FromTdsInternalException ((TdsInternalException
) ex
);
853 } catch (TdsInternalException ex
) {
855 throw SqlException
.FromTdsInternalException ((TdsInternalException
) ex
);
858 case CommandType
.Text
:
859 string sql
= String
.Format ("{0}{1};{2}", sql1
.ToString (), CommandText
, sql2
.ToString ());
862 ar
= Connection
.Tds
.BeginExecuteQuery (sql
, parms
, callback
, state
);
864 ar
= Connection
.Tds
.BeginExecuteNonQuery (sql
, parms
, callback
, state
);
865 } catch (TdsTimeoutException ex
) {
866 Connection
.Tds
.Reset ();
867 throw SqlException
.FromTdsInternalException ((TdsInternalException
) ex
);
868 } catch (TdsInternalException ex
) {
870 throw SqlException
.FromTdsInternalException ((TdsInternalException
) ex
);
877 Connection
.Tds
.ExecPrepared (preparedStatement
, parms
, CommandTimeout
, wantResults
);
878 } catch (TdsTimeoutException ex
) {
879 Connection
.Tds
.Reset ();
880 throw SqlException
.FromTdsInternalException ((TdsInternalException
) ex
);
881 } catch (TdsInternalException ex
) {
883 throw SqlException
.FromTdsInternalException ((TdsInternalException
) ex
);
889 internal void EndExecuteInternal (IAsyncResult ar
)
891 SqlAsyncResult sqlResult
= ( (SqlAsyncResult
) ar
);
892 Connection
.Tds
.WaitFor (sqlResult
.InternalResult
);
893 Connection
.Tds
.CheckAndThrowException (sqlResult
.InternalResult
);
896 public IAsyncResult
BeginExecuteNonQuery ()
898 return BeginExecuteNonQuery (null, null);
901 public IAsyncResult
BeginExecuteNonQuery (AsyncCallback callback
, object stateObject
)
903 ValidateCommand ("BeginExecuteNonQuery", true);
904 SqlAsyncResult ar
= new SqlAsyncResult (callback
, stateObject
);
905 ar
.EndMethod
= "EndExecuteNonQuery";
906 ar
.InternalResult
= BeginExecuteInternal (CommandBehavior
.Default
, false, ar
.BubbleCallback
, ar
);
910 public int EndExecuteNonQuery (IAsyncResult asyncResult
)
912 ValidateAsyncResult (asyncResult
, "EndExecuteNonQuery");
913 EndExecuteInternal (asyncResult
);
915 int ret
= Connection
.Tds
.RecordsAffected
;
917 GetOutputParameters ();
918 ((SqlAsyncResult
) asyncResult
).Ended
= true;
922 public IAsyncResult
BeginExecuteReader ()
924 return BeginExecuteReader (null, null, CommandBehavior
.Default
);
927 public IAsyncResult
BeginExecuteReader (CommandBehavior behavior
)
929 return BeginExecuteReader (null, null, behavior
);
932 public IAsyncResult
BeginExecuteReader (AsyncCallback callback
, object stateObject
)
934 return BeginExecuteReader (callback
, stateObject
, CommandBehavior
.Default
);
937 public IAsyncResult
BeginExecuteReader (AsyncCallback callback
, object stateObject
, CommandBehavior behavior
)
939 ValidateCommand ("BeginExecuteReader", true);
940 this.behavior
= behavior
;
941 SqlAsyncResult ar
= new SqlAsyncResult (callback
, stateObject
);
942 ar
.EndMethod
= "EndExecuteReader";
943 IAsyncResult tdsResult
= BeginExecuteInternal (behavior
, true,
944 ar
.BubbleCallback
, stateObject
);
945 ar
.InternalResult
= tdsResult
;
949 public SqlDataReader
EndExecuteReader (IAsyncResult asyncResult
)
951 ValidateAsyncResult (asyncResult
, "EndExecuteReader");
952 EndExecuteInternal (asyncResult
);
953 SqlDataReader reader
= null;
955 reader
= new SqlDataReader (this);
956 } catch (TdsTimeoutException e
) {
957 throw SqlException
.FromTdsInternalException ((TdsInternalException
) e
);
958 } catch (TdsInternalException e
) {
959 // if behavior is closeconnection, even if it throws exception
960 // the connection has to be closed.
961 if ((behavior
& CommandBehavior
.CloseConnection
) != 0)
963 throw SqlException
.FromTdsInternalException ((TdsInternalException
) e
);
966 ((SqlAsyncResult
) asyncResult
).Ended
= true;
970 public IAsyncResult
BeginExecuteXmlReader (AsyncCallback callback
, object stateObject
)
972 ValidateCommand ("BeginExecuteXmlReader", true);
973 SqlAsyncResult ar
= new SqlAsyncResult (callback
, stateObject
);
974 ar
.EndMethod
= "EndExecuteXmlReader";
975 ar
.InternalResult
= BeginExecuteInternal (behavior
, true,
976 ar
.BubbleCallback
, stateObject
);
980 public IAsyncResult
BeginExecuteXmlReader ()
982 return BeginExecuteXmlReader (null, null);
986 public XmlReader
EndExecuteXmlReader (IAsyncResult asyncResult
)
988 ValidateAsyncResult (asyncResult
, "EndExecuteXmlReader");
989 EndExecuteInternal (asyncResult
);
990 SqlDataReader reader
= new SqlDataReader (this);
991 SqlXmlTextReader textReader
= new SqlXmlTextReader (reader
);
992 XmlReader xmlReader
= new XmlTextReader (textReader
);
993 ((SqlAsyncResult
) asyncResult
).Ended
= true;
997 internal void ValidateAsyncResult (IAsyncResult ar
, string endMethod
)
1000 throw new ArgumentException ("result passed is null!");
1001 if (! (ar
is SqlAsyncResult
))
1002 throw new ArgumentException (String
.Format ("cannot test validity of types {0}",
1004 SqlAsyncResult result
= (SqlAsyncResult
) ar
;
1005 if (result
.EndMethod
!= endMethod
)
1006 throw new InvalidOperationException (String
.Format ("Mismatched {0} called for AsyncResult. " +
1007 "Expected call to {1} but {0} is called instead.",
1008 endMethod
, result
.EndMethod
));
1010 throw new InvalidOperationException (String
.Format ("The method {0} cannot be called " +
1011 "more than once for the same AsyncResult.", endMethod
));
1014 #endregion // Asynchronous Methods
1016 public event StatementCompletedEventHandler StatementCompleted
;