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;
47 using System.Data.Sql;
48 using System.Runtime.InteropServices;
52 namespace System.Data.SqlClient {
53 [DesignerAttribute ("Microsoft.VSDesigner.Data.VS.SqlCommandDesigner, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.ComponentModel.Design.IDesigner")]
54 [ToolboxItemAttribute ("System.Drawing.Design.ToolboxItem, "+ Consts.AssemblySystem_Drawing)]
55 [DefaultEventAttribute ("RecordsAffected")]
56 public sealed class SqlCommand : DbCommand, IDbCommand, ICloneable
60 const int DEFAULT_COMMAND_TIMEOUT = 30;
63 bool designTimeVisible;
65 CommandType commandType;
66 SqlConnection connection;
67 SqlTransaction transaction;
68 UpdateRowSource updatedRowSource;
69 CommandBehavior behavior = CommandBehavior.Default;
70 SqlParameterCollection parameters;
71 string preparedStatement;
73 SqlNotificationRequest notification;
74 bool notificationAutoEnlist;
81 : this (String.Empty, null, null)
85 public SqlCommand (string cmdText)
86 : this (cmdText, null, null)
90 public SqlCommand (string cmdText, SqlConnection connection)
91 : this (cmdText, connection, null)
95 public SqlCommand (string cmdText, SqlConnection connection, SqlTransaction transaction)
97 this.commandText = cmdText;
98 this.connection = connection;
99 this.transaction = transaction;
100 this.commandType = CommandType.Text;
101 this.updatedRowSource = UpdateRowSource.Both;
103 this.commandTimeout = DEFAULT_COMMAND_TIMEOUT;
104 notificationAutoEnlist = true;
105 designTimeVisible = true;
106 parameters = new SqlParameterCollection (this);
109 private SqlCommand(string commandText, SqlConnection connection, SqlTransaction transaction, CommandType commandType, UpdateRowSource updatedRowSource, bool designTimeVisible, int commandTimeout, SqlParameterCollection parameters)
111 this.commandText = commandText;
112 this.connection = connection;
113 this.transaction = transaction;
114 this.commandType = commandType;
115 this.updatedRowSource = updatedRowSource;
116 this.designTimeVisible = designTimeVisible;
117 this.commandTimeout = commandTimeout;
118 this.parameters = new SqlParameterCollection(this);
119 for (int i = 0;i < parameters.Count;i++)
120 this.parameters.Add(((ICloneable)parameters[i]).Clone());
123 #endregion // Constructors
127 internal CommandBehavior CommandBehavior {
128 get { return behavior; }
132 [EditorAttribute ("Microsoft.VSDesigner.Data.SQL.Design.SqlCommandTextEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]
133 [RefreshProperties (RefreshProperties.All)]
138 if (commandText == null)
143 if (value != commandText && preparedStatement != null)
152 get { return commandTimeout; }
155 throw new ArgumentException ("The property value assigned is less than 0.",
157 commandTimeout = value;
161 [DefaultValue (CommandType.Text)]
162 [RefreshProperties (RefreshProperties.All)]
165 CommandType CommandType {
166 get { return commandType; }
168 if (value == CommandType.TableDirect)
169 throw new ArgumentOutOfRangeException ("CommandType.TableDirect is not supported " +
170 "by the Mono SqlClient Data Provider.");
172 ExceptionHelper.CheckEnumValue (typeof (CommandType), value);
177 [DefaultValue (null)]
178 [EditorAttribute ("Microsoft.VSDesigner.Data.Design.DbConnectionEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]
181 SqlConnection Connection {
182 get { return connection; }
186 if (connection != null && connection.DataReader != null)
187 throw new InvalidOperationException ("The connection is busy fetching data.");
194 [DefaultValue (true)]
196 [EditorBrowsable (EditorBrowsableState.Never)]
199 bool DesignTimeVisible {
200 get { return designTimeVisible; }
201 set { designTimeVisible = value; }
204 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
207 SqlParameterCollection Parameters {
208 get { return parameters; }
212 get { return Connection.Tds; }
217 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
218 public new SqlTransaction Transaction {
220 if (transaction != null && !transaction.IsOpen)
227 if (connection != null && connection.DataReader != null)
228 throw new InvalidOperationException ("The connection is busy fetching data.");
234 [DefaultValue (UpdateRowSource.Both)]
237 UpdateRowSource UpdatedRowSource {
238 get { return updatedRowSource; }
240 ExceptionHelper.CheckEnumValue (typeof (UpdateRowSource), value);
241 updatedRowSource = value;
246 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
247 public SqlNotificationRequest Notification {
248 get { return notification; }
249 set { notification = value; }
252 [DefaultValue (true)]
253 public bool NotificationAutoEnlist {
254 get { return notificationAutoEnlist; }
255 set { notificationAutoEnlist = value; }
265 if (Connection == null || Connection.Tds == null)
267 Connection.Tds.Cancel ();
270 public SqlCommand Clone ()
272 return new SqlCommand (commandText, connection, transaction, commandType, updatedRowSource, designTimeVisible, commandTimeout, parameters);
275 internal void CloseDataReader ()
277 if (Connection != null) {
278 Connection.DataReader = null;
280 if ((behavior & CommandBehavior.CloseConnection) != 0)
284 Tds.SequentialAccess = false;
287 // Reset the behavior
288 behavior = CommandBehavior.Default;
291 public new SqlParameter CreateParameter ()
293 return new SqlParameter ();
296 private string EscapeProcName (string name, bool schema)
299 string tmpProcName = name.Trim ();
300 int procNameLen = tmpProcName.Length;
301 char[] brkts = new char [] {'[', ']'};
302 bool foundMatching = false;
303 int start = 0, count = procNameLen;
304 int sindex = -1, eindex = -1;
306 // We try to match most of the "brackets" combination here, however
307 // there could be other combinations that may generate a different type
308 // of exception in MS.NET
310 if (procNameLen > 1) {
311 if ((sindex = tmpProcName.IndexOf ('[')) <= 0)
312 foundMatching = true;
314 foundMatching = false;
316 if (foundMatching == true && sindex > -1) {
317 eindex = tmpProcName.IndexOf (']');
318 if (sindex > eindex && eindex != -1) {
319 foundMatching = false;
320 } else if (eindex == procNameLen-1) {
321 if (tmpProcName.IndexOfAny (brkts, 1, procNameLen-2) != -1) {
322 foundMatching = false;
325 count = procNameLen - 2;
327 } else if (eindex == -1 && schema) {
328 foundMatching = true;
330 foundMatching = false;
335 procName = tmpProcName.Substring (start, count);
337 throw new ArgumentException (String.Format ("SqlCommand.CommandText property value is an invalid multipart name {0}, incorrect usage of quotes", CommandText));
339 procName = tmpProcName;
344 internal void DeriveParameters ()
346 if (commandType != CommandType.StoredProcedure)
347 throw new InvalidOperationException (String.Format ("SqlCommand DeriveParameters only supports CommandType.StoredProcedure, not CommandType.{0}", commandType));
348 ValidateCommand ("DeriveParameters", false);
350 string procName = CommandText;
351 string schemaName = String.Empty;
352 int dotPosition = procName.LastIndexOf ('.');
354 // Procedure name can be: [database].[user].[procname]
355 if (dotPosition >= 0) {
356 schemaName = procName.Substring (0, dotPosition);
357 procName = procName.Substring (dotPosition + 1);
358 if ((dotPosition = schemaName.LastIndexOf ('.')) >= 0)
359 schemaName = schemaName.Substring (dotPosition + 1);
362 procName = EscapeProcName (procName, false);
363 schemaName = EscapeProcName (schemaName, true);
365 SqlParameterCollection localParameters = new SqlParameterCollection (this);
366 localParameters.Add ("@procedure_name", SqlDbType.NVarChar, procName.Length).Value = procName;
367 if (schemaName.Length > 0)
368 localParameters.Add ("@procedure_schema", SqlDbType.NVarChar, schemaName.Length).Value = schemaName;
370 string sql = "sp_procedure_params_rowset";
373 Connection.Tds.ExecProc (sql, localParameters.MetaParameters, 0, true);
374 } catch (TdsTimeoutException ex) {
375 Connection.Tds.Reset ();
376 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
377 } catch (TdsInternalException ex) {
379 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
382 SqlDataReader reader = new SqlDataReader (this);
384 object[] dbValues = new object[reader.FieldCount];
386 while (reader.Read ()) {
387 reader.GetValues (dbValues);
388 parameters.Add (new SqlParameter (dbValues));
392 if (parameters.Count == 0)
393 throw new InvalidOperationException ("Stored procedure '" + procName + "' does not exist.");
396 private void Execute (bool wantResults)
399 Connection.Tds.RecordsAffected = -1;
400 TdsMetaParameterCollection parms = Parameters.MetaParameters;
401 foreach (TdsMetaParameter param in parms) {
402 param.Validate (index++);
405 if (preparedStatement == null) {
406 bool schemaOnly = ((behavior & CommandBehavior.SchemaOnly) > 0);
407 bool keyInfo = ((behavior & CommandBehavior.KeyInfo) > 0);
409 StringBuilder sql1 = new StringBuilder ();
410 StringBuilder sql2 = new StringBuilder ();
412 if (schemaOnly || keyInfo)
413 sql1.Append ("SET FMTONLY OFF;");
415 sql1.Append ("SET NO_BROWSETABLE ON;");
416 sql2.Append ("SET NO_BROWSETABLE OFF;");
419 sql1.Append ("SET FMTONLY ON;");
420 sql2.Append ("SET FMTONLY OFF;");
423 switch (CommandType) {
424 case CommandType.StoredProcedure:
426 if (keyInfo || schemaOnly)
427 Connection.Tds.Execute (sql1.ToString ());
428 Connection.Tds.ExecProc (CommandText, parms, CommandTimeout, wantResults);
429 if (keyInfo || schemaOnly)
430 Connection.Tds.Execute (sql2.ToString ());
431 } catch (TdsTimeoutException ex) {
432 // If it is a timeout exception there can be many reasons:
433 // 1) Network is down/server is down/not reachable
434 // 2) Somebody has an exclusive lock on Table/DB
435 // In any of these cases, don't close the connection. Let the user do it
436 Connection.Tds.Reset ();
437 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
438 } catch (TdsInternalException ex) {
440 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
443 case CommandType.Text:
445 if (sql2.Length > 0) {
446 sql = String.Format ("{0}{1};{2}", sql1.ToString (), CommandText, sql2.ToString ());
448 sql = String.Format ("{0}{1}", sql1.ToString (), CommandText);
451 Connection.Tds.Execute (sql, parms, CommandTimeout, wantResults);
452 } catch (TdsTimeoutException ex) {
453 Connection.Tds.Reset ();
454 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
455 } catch (TdsInternalException ex) {
457 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
464 Connection.Tds.ExecPrepared (preparedStatement, parms, CommandTimeout, wantResults);
465 } catch (TdsTimeoutException ex) {
466 Connection.Tds.Reset ();
467 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
468 } catch (TdsInternalException ex) {
470 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
477 int ExecuteNonQuery ()
479 ValidateCommand ("ExecuteNonQuery", false);
481 behavior = CommandBehavior.Default;
485 result = Connection.Tds.RecordsAffected;
486 } catch (TdsTimeoutException e) {
487 Connection.Tds.Reset ();
488 throw SqlException.FromTdsInternalException ((TdsInternalException) e);
491 GetOutputParameters ();
495 public new SqlDataReader ExecuteReader ()
497 return ExecuteReader (CommandBehavior.Default);
500 public new SqlDataReader ExecuteReader (CommandBehavior behavior)
502 ValidateCommand ("ExecuteReader", false);
503 if ((behavior & CommandBehavior.SingleRow) != 0)
504 behavior |= CommandBehavior.SingleResult;
505 this.behavior = behavior;
506 if ((behavior & CommandBehavior.SequentialAccess) != 0)
507 Tds.SequentialAccess = true;
510 Connection.DataReader = new SqlDataReader (this);
511 return Connection.DataReader;
513 if ((behavior & CommandBehavior.CloseConnection) != 0)
521 object ExecuteScalar ()
524 object result = null;
525 ValidateCommand ("ExecuteScalar", false);
526 behavior = CommandBehavior.Default;
530 if (Connection.Tds.NextResult () && Connection.Tds.NextRow ())
531 result = Connection.Tds.ColumnValues[0];
533 if (commandType == CommandType.StoredProcedure) {
534 Connection.Tds.SkipToEnd ();
535 GetOutputParameters ();
537 } catch (TdsTimeoutException ex) {
538 Connection.Tds.Reset ();
539 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
540 } catch (TdsInternalException ex) {
542 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
551 public XmlReader ExecuteXmlReader ()
553 ValidateCommand ("ExecuteXmlReader", false);
554 behavior = CommandBehavior.Default;
557 } catch (TdsTimeoutException e) {
558 Connection.Tds.Reset ();
559 throw SqlException.FromTdsInternalException ((TdsInternalException) e);
562 SqlDataReader dataReader = new SqlDataReader (this);
563 SqlXmlTextReader textReader = new SqlXmlTextReader (dataReader);
564 XmlReader xmlReader = new XmlTextReader (textReader);
568 internal void GetOutputParameters ()
570 IList list = Connection.Tds.OutputParameters;
572 if (list != null && list.Count > 0) {
575 foreach (SqlParameter parameter in parameters) {
576 if (parameter.Direction != ParameterDirection.Input &&
577 parameter.Direction != ParameterDirection.ReturnValue) {
578 parameter.Value = list [index];
581 if (index >= list.Count)
587 object ICloneable.Clone ()
589 return new SqlCommand (commandText, connection, transaction, commandType, updatedRowSource, designTimeVisible, commandTimeout, parameters);
594 protected override void Dispose (bool disposing)
596 if (disposed) return;
599 if (Connection != null)
600 Connection.DataReader = null;
602 base.Dispose (disposing);
610 if (Connection == null)
611 throw new NullReferenceException ();
613 if (CommandType == CommandType.StoredProcedure || CommandType == CommandType.Text && Parameters.Count == 0)
616 ValidateCommand ("Prepare", false);
619 foreach (SqlParameter param in Parameters)
620 param.CheckIfInitialized ();
621 } catch (Exception e) {
622 throw new InvalidOperationException ("SqlCommand.Prepare requires " + e.Message);
625 preparedStatement = Connection.Tds.Prepare (CommandText, Parameters.MetaParameters);
628 public void ResetCommandTimeout ()
630 commandTimeout = DEFAULT_COMMAND_TIMEOUT;
633 private void Unprepare ()
635 Connection.Tds.Unprepare (preparedStatement);
636 preparedStatement = null;
639 private void ValidateCommand (string method, bool async)
641 if (Connection == null)
642 throw new InvalidOperationException (String.Format ("{0}: A Connection object is required to continue.", method));
643 if (Transaction == null && Connection.Transaction != null)
644 throw new InvalidOperationException (String.Format (
645 "{0} requires a transaction if the command's connection is in a pending transaction.",
647 if (Transaction != null && Transaction.Connection != Connection)
648 throw new InvalidOperationException ("The connection does not have the same transaction as the command.");
649 if (Connection.State != ConnectionState.Open)
650 throw new InvalidOperationException (String.Format ("{0} requires an open connection to continue. This connection is closed.", method));
651 if (CommandText.Length == 0)
652 throw new InvalidOperationException (String.Format ("{0}: CommandText has not been set for this Command.", method));
653 if (Connection.DataReader != null)
654 throw new InvalidOperationException ("There is already an open DataReader associated with this Connection which must be closed first.");
655 if (Connection.XmlReader != null)
656 throw new InvalidOperationException ("There is already an open XmlReader associated with this Connection which must be closed first.");
657 if (async && !Connection.AsyncProcessing)
658 throw new InvalidOperationException ("This Connection object is not " +
659 "in Asynchronous mode. Use 'Asynchronous" +
660 " Processing = true' to set it.");
663 protected override DbParameter CreateDbParameter ()
665 return CreateParameter ();
668 protected override DbDataReader ExecuteDbDataReader (CommandBehavior behavior)
670 return ExecuteReader (behavior);
673 protected override DbConnection DbConnection {
674 get { return Connection; }
675 set { Connection = (SqlConnection) value; }
678 protected override DbParameterCollection DbParameterCollection {
679 get { return Parameters; }
682 protected override DbTransaction DbTransaction {
683 get { return Transaction; }
684 set { Transaction = (SqlTransaction) value; }
687 #endregion // Methods
689 #region Asynchronous Methods
691 internal IAsyncResult BeginExecuteInternal (CommandBehavior behavior,
693 AsyncCallback callback,
696 IAsyncResult ar = null;
697 Connection.Tds.RecordsAffected = -1;
698 TdsMetaParameterCollection parms = Parameters.MetaParameters;
699 if (preparedStatement == null) {
700 bool schemaOnly = ((behavior & CommandBehavior.SchemaOnly) > 0);
701 bool keyInfo = ((behavior & CommandBehavior.KeyInfo) > 0);
703 StringBuilder sql1 = new StringBuilder ();
704 StringBuilder sql2 = new StringBuilder ();
706 if (schemaOnly || keyInfo)
707 sql1.Append ("SET FMTONLY OFF;");
709 sql1.Append ("SET NO_BROWSETABLE ON;");
710 sql2.Append ("SET NO_BROWSETABLE OFF;");
713 sql1.Append ("SET FMTONLY ON;");
714 sql2.Append ("SET FMTONLY OFF;");
716 switch (CommandType) {
717 case CommandType.StoredProcedure:
720 if (keyInfo || schemaOnly)
721 prolog = sql1.ToString ();
722 if (keyInfo || schemaOnly)
723 epilog = sql2.ToString ();
725 ar = Connection.Tds.BeginExecuteProcedure (prolog,
732 } catch (TdsTimeoutException ex) {
733 Connection.Tds.Reset ();
734 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
735 } catch (TdsInternalException ex) {
737 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
740 case CommandType.Text:
741 string sql = String.Format ("{0}{1};{2}", sql1.ToString (), CommandText, sql2.ToString ());
744 ar = Connection.Tds.BeginExecuteQuery (sql, parms, callback, state);
746 ar = Connection.Tds.BeginExecuteNonQuery (sql, parms, callback, state);
747 } catch (TdsTimeoutException ex) {
748 Connection.Tds.Reset ();
749 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
750 } catch (TdsInternalException ex) {
752 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
759 Connection.Tds.ExecPrepared (preparedStatement, parms, CommandTimeout, wantResults);
760 } catch (TdsTimeoutException ex) {
761 Connection.Tds.Reset ();
762 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
763 } catch (TdsInternalException ex) {
765 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
771 internal void EndExecuteInternal (IAsyncResult ar)
773 SqlAsyncResult sqlResult = ( (SqlAsyncResult) ar);
774 Connection.Tds.WaitFor (sqlResult.InternalResult);
775 Connection.Tds.CheckAndThrowException (sqlResult.InternalResult);
778 public IAsyncResult BeginExecuteNonQuery ()
780 return BeginExecuteNonQuery (null, null);
783 public IAsyncResult BeginExecuteNonQuery (AsyncCallback callback, object stateObject)
785 ValidateCommand ("BeginExecuteNonQuery", true);
786 SqlAsyncResult ar = new SqlAsyncResult (callback, stateObject);
787 ar.EndMethod = "EndExecuteNonQuery";
788 ar.InternalResult = BeginExecuteInternal (CommandBehavior.Default, false, ar.BubbleCallback, ar);
792 public int EndExecuteNonQuery (IAsyncResult asyncResult)
794 ValidateAsyncResult (asyncResult, "EndExecuteNonQuery");
795 EndExecuteInternal (asyncResult);
797 int ret = Connection.Tds.RecordsAffected;
799 GetOutputParameters ();
800 ((SqlAsyncResult) asyncResult).Ended = true;
804 public IAsyncResult BeginExecuteReader ()
806 return BeginExecuteReader (null, null, CommandBehavior.Default);
809 public IAsyncResult BeginExecuteReader (CommandBehavior behavior)
811 return BeginExecuteReader (null, null, behavior);
814 public IAsyncResult BeginExecuteReader (AsyncCallback callback, object stateObject)
816 return BeginExecuteReader (callback, stateObject, CommandBehavior.Default);
819 public IAsyncResult BeginExecuteReader (AsyncCallback callback, object stateObject, CommandBehavior behavior)
821 ValidateCommand ("BeginExecuteReader", true);
822 this.behavior = behavior;
823 SqlAsyncResult ar = new SqlAsyncResult (callback, stateObject);
824 ar.EndMethod = "EndExecuteReader";
825 IAsyncResult tdsResult = BeginExecuteInternal (behavior, true,
826 ar.BubbleCallback, stateObject);
827 ar.InternalResult = tdsResult;
831 public SqlDataReader EndExecuteReader (IAsyncResult asyncResult)
833 ValidateAsyncResult (asyncResult, "EndExecuteReader");
834 EndExecuteInternal (asyncResult);
835 SqlDataReader reader = null;
837 reader = new SqlDataReader (this);
838 } catch (TdsTimeoutException e) {
839 throw SqlException.FromTdsInternalException ((TdsInternalException) e);
840 } catch (TdsInternalException e) {
841 // if behavior is closeconnection, even if it throws exception
842 // the connection has to be closed.
843 if ((behavior & CommandBehavior.CloseConnection) != 0)
845 throw SqlException.FromTdsInternalException ((TdsInternalException) e);
848 ((SqlAsyncResult) asyncResult).Ended = true;
852 public IAsyncResult BeginExecuteXmlReader (AsyncCallback callback, object stateObject)
854 ValidateCommand ("BeginExecuteXmlReader", true);
855 SqlAsyncResult ar = new SqlAsyncResult (callback, stateObject);
856 ar.EndMethod = "EndExecuteXmlReader";
857 ar.InternalResult = BeginExecuteInternal (behavior, true,
858 ar.BubbleCallback, stateObject);
862 public IAsyncResult BeginExecuteXmlReader ()
864 return BeginExecuteXmlReader (null, null);
868 public XmlReader EndExecuteXmlReader (IAsyncResult asyncResult)
870 ValidateAsyncResult (asyncResult, "EndExecuteXmlReader");
871 EndExecuteInternal (asyncResult);
872 SqlDataReader reader = new SqlDataReader (this);
873 SqlXmlTextReader textReader = new SqlXmlTextReader (reader);
874 XmlReader xmlReader = new XmlTextReader (textReader);
875 ((SqlAsyncResult) asyncResult).Ended = true;
879 internal void ValidateAsyncResult (IAsyncResult ar, string endMethod)
882 throw new ArgumentException ("result passed is null!");
883 if (! (ar is SqlAsyncResult))
884 throw new ArgumentException (String.Format ("cannot test validity of types {0}",
886 SqlAsyncResult result = (SqlAsyncResult) ar;
887 if (result.EndMethod != endMethod)
888 throw new InvalidOperationException (String.Format ("Mismatched {0} called for AsyncResult. " +
889 "Expected call to {1} but {0} is called instead.",
890 endMethod, result.EndMethod));
892 throw new InvalidOperationException (String.Format ("The method {0} cannot be called " +
893 "more than once for the same AsyncResult.", endMethod));
896 #endregion // Asynchronous Methods
898 public event StatementCompletedEventHandler StatementCompleted;