Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSureshkumar T <suresh@mono-cvs.ximian.com>2005-04-07 18:25:50 +0400
committerSureshkumar T <suresh@mono-cvs.ximian.com>2005-04-07 18:25:50 +0400
commitf943410d7265cb08c076852614fe80db63186c77 (patch)
tree6d7c3b7f18fb68ec0d7b5016ab762d55259a3090 /mcs/class/System.Data/System.Data.SqlClient
parent2e3eb053ab9baa399d57a9b8c6988d732ab1335d (diff)
In System.Data/System.Data.SqlClient: Implemented asynchronous command execution.
In Mono.Data.Tds: Implemented asynchronous command execution at tds driver level. Implemented by Sureshkumar T <tsureshkumar@novell.com> & Ankit Jain <radical@corewars.org> svn path=/trunk/mcs/; revision=42641
Diffstat (limited to 'mcs/class/System.Data/System.Data.SqlClient')
-rwxr-xr-xmcs/class/System.Data/System.Data.SqlClient/ChangeLog14
-rw-r--r--mcs/class/System.Data/System.Data.SqlClient/SqlAsyncResult.cs139
-rw-r--r--mcs/class/System.Data/System.Data.SqlClient/SqlAsyncState.cs56
-rw-r--r--mcs/class/System.Data/System.Data.SqlClient/SqlCommand.cs216
-rw-r--r--mcs/class/System.Data/System.Data.SqlClient/SqlConnection.cs29
5 files changed, 454 insertions, 0 deletions
diff --git a/mcs/class/System.Data/System.Data.SqlClient/ChangeLog b/mcs/class/System.Data/System.Data.SqlClient/ChangeLog
index bfd627d25ab..11a76042605 100755
--- a/mcs/class/System.Data/System.Data.SqlClient/ChangeLog
+++ b/mcs/class/System.Data/System.Data.SqlClient/ChangeLog
@@ -1,3 +1,17 @@
+2005-04-07 Sureshkumar T <tsureshkumar@novell.com>
+ Ankit Jain <radical@corewars.org>
+
+ * SqlConnection.cs: Implemented additional connection string
+ property "Asynchronous Processing".
+
+ * SqlCommand.cs: Implemented Asynchronous command execution API.
+
+ * SqlAsyncState.cs: A internal state object for asynchronous
+ operations.
+
+ * SqlAsyncResult.cs: Added. Class to hold result for asynchronous
+ queries.
+
2005-03-28 Sureshkumar T <tsureshkumar@novell.com>
* SqlCommand.cs: Execute: Add a semicolon at the end of
diff --git a/mcs/class/System.Data/System.Data.SqlClient/SqlAsyncResult.cs b/mcs/class/System.Data/System.Data.SqlClient/SqlAsyncResult.cs
new file mode 100644
index 00000000000..ff85db23bac
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.SqlClient/SqlAsyncResult.cs
@@ -0,0 +1,139 @@
+//
+// System.Data.SqlClient.SqlAsyncResult.cs
+//
+// Author:
+// T Sureshkumar <tsureshkumar@novell.com>
+// Ankit Jain <radical@corewars.org>
+//
+
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+
+#if NET_2_0
+using System;
+using System.Threading;
+
+namespace System.Data.SqlClient
+{
+ internal class SqlAsyncResult : IAsyncResult
+ {
+ private SqlAsyncState _sqlState;
+ private WaitHandle _waitHandle;
+ private bool _completed = false;
+ private bool _completedSyncly = false;
+ private bool _ended = false;
+ private AsyncCallback _userCallback = null;
+ private object _retValue;
+ private string _endMethod;
+ private IAsyncResult _internal;
+
+ public SqlAsyncResult (AsyncCallback userCallback, SqlAsyncState sqlState)
+ {
+ _sqlState = sqlState;
+ _userCallback = userCallback;
+ _waitHandle = new ManualResetEvent (false);
+ }
+
+ public SqlAsyncResult (AsyncCallback userCallback, object state)
+ {
+ _sqlState = new SqlAsyncState (state);
+ _userCallback = userCallback;
+ _waitHandle = new ManualResetEvent (false);
+ }
+
+ public object AsyncState
+ {
+ get { return _sqlState.UserState; }
+ }
+
+ internal SqlAsyncState SqlAsyncState
+ {
+ get { return _sqlState; }
+ }
+
+ public WaitHandle AsyncWaitHandle
+ {
+ get { return _waitHandle; }
+
+ }
+
+ public bool IsCompleted
+ {
+ get { return _completed; }
+ }
+
+ public bool CompletedSynchronously
+ {
+ get { return _completedSyncly; }
+ }
+
+ internal object ReturnValue
+ {
+ get { return _retValue; }
+ set { _retValue = value; }
+ }
+
+ public string EndMethod
+ {
+ get { return _endMethod; }
+ set { _endMethod = value; }
+ }
+
+ public bool Ended
+ {
+ get { return _ended; }
+ set { _ended = value; }
+ }
+
+
+ internal IAsyncResult InternalResult
+ {
+ get { return _internal; }
+ set { _internal = value; }
+ }
+
+ public AsyncCallback BubbleCallback
+ {
+ get { return new AsyncCallback (Bubbleback); }
+
+ }
+
+ internal void MarkComplete ()
+ {
+ _completed = true;
+ ((ManualResetEvent)_waitHandle).Set ();
+
+ if (_userCallback != null)
+ _userCallback (this);
+ }
+
+ public void Bubbleback (IAsyncResult ar)
+ {
+ this.MarkComplete ();
+ }
+ }
+}
+
+#endif // NET_2_0
diff --git a/mcs/class/System.Data/System.Data.SqlClient/SqlAsyncState.cs b/mcs/class/System.Data/System.Data.SqlClient/SqlAsyncState.cs
new file mode 100644
index 00000000000..7f733d79877
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.SqlClient/SqlAsyncState.cs
@@ -0,0 +1,56 @@
+//
+// System.Data.SqlClient.SqlAsyncState.cs
+//
+// Author:
+// T Sureshkumar <tsureshkumar@novell.com>
+// Ankit Jain <radical@corewars.org>
+//
+
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using System;
+using System.Net.Sockets;
+
+
+namespace System.Data.SqlClient
+{
+ internal class SqlAsyncState
+ {
+ object _userState;
+
+ public SqlAsyncState (object userState)
+ {
+ _userState = userState;
+ }
+
+ public object UserState
+ {
+ get {return _userState;}
+ set {_userState = value;}
+ }
+ }
+}
+#endif // NET_2_0
diff --git a/mcs/class/System.Data/System.Data.SqlClient/SqlCommand.cs b/mcs/class/System.Data/System.Data.SqlClient/SqlCommand.cs
index 0e632576e4f..50bdeb99868 100644
--- a/mcs/class/System.Data/System.Data.SqlClient/SqlCommand.cs
+++ b/mcs/class/System.Data/System.Data.SqlClient/SqlCommand.cs
@@ -542,6 +542,12 @@ namespace System.Data.SqlClient {
throw new InvalidOperationException ("There is already an open DataReader associated with this Connection which must be closed first.");
if (Connection.XmlReader != null)
throw new InvalidOperationException ("There is already an open XmlReader associated with this Connection which must be closed first.");
+#if NET_2_0
+ if (method.StartsWith ("Begin") && !Connection.AsyncProcessing)
+ throw new InvalidOperationException ("This Connection object is not " +
+ "in Asynchronous mode. Use 'Asynchronous" +
+ " Processing = true' to set it.");
+#endif // NET_2_0
}
#if NET_2_0
@@ -579,5 +585,215 @@ namespace System.Data.SqlClient {
#endif // NET_2_0
#endregion // Methods
+
+#if NET_2_0
+ #region Asynchronous Methods
+
+ internal IAsyncResult BeginExecuteInternal (CommandBehavior behavior,
+ bool wantResults,
+ AsyncCallback callback,
+ object state)
+ {
+ IAsyncResult ar = null;
+ Connection.Tds.RecordsAffected = 0;
+ TdsMetaParameterCollection parms = Parameters.MetaParameters;
+ if (preparedStatement == null) {
+ bool schemaOnly = ((behavior & CommandBehavior.SchemaOnly) > 0);
+ bool keyInfo = ((behavior & CommandBehavior.KeyInfo) > 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:
+ string prolog = "";
+ string epilog = "";
+ if (keyInfo || schemaOnly)
+ prolog = sql1.ToString ();
+ if (keyInfo || schemaOnly)
+ epilog = sql2.ToString ();
+ Connection.Tds.BeginExecuteProcedure (prolog,
+ epilog,
+ CommandText,
+ !wantResults,
+ parms,
+ callback,
+ state);
+
+ break;
+ case CommandType.Text:
+ string sql = String.Format ("{0}{1};{2}", sql1.ToString (), CommandText, sql2.ToString ());
+ if (wantResults)
+ ar = Connection.Tds.BeginExecuteQuery (sql, parms,
+ callback, state);
+ else
+ ar = Connection.Tds.BeginExecuteNonQuery (sql, parms, callback, state);
+ break;
+ }
+ }
+ else
+ Connection.Tds.ExecPrepared (preparedStatement, parms, CommandTimeout, wantResults);
+
+ return ar;
+
+ }
+
+ internal void EndExecuteInternal (IAsyncResult ar)
+ {
+ SqlAsyncResult sqlResult = ( (SqlAsyncResult) ar);
+ Connection.Tds.WaitFor (sqlResult.InternalResult);
+ Connection.Tds.CheckAndThrowException (sqlResult.InternalResult);
+ }
+
+ public IAsyncResult BeginExecuteNonQuery ()
+ {
+ return BeginExecuteNonQuery (null, null);
+ }
+
+ public IAsyncResult BeginExecuteNonQuery (AsyncCallback callback, object state)
+ {
+ ValidateCommand ("BeginExecuteNonQuery");
+ SqlAsyncResult ar = new SqlAsyncResult (callback, state);
+ ar.EndMethod = "EndExecuteNonQuery";
+ ar.InternalResult = BeginExecuteInternal (CommandBehavior.Default, false, ar.BubbleCallback, ar);
+ return ar;
+ }
+
+ public int EndExecuteNonQuery (IAsyncResult ar)
+ {
+ ValidateAsyncResult (ar, "EndExecuteNonQuery");
+ EndExecuteInternal (ar);
+
+ int ret;
+ if (commandType == CommandType.StoredProcedure)
+ ret = -1;
+ else {
+ // .NET documentation says that except for INSERT, UPDATE and
+ // DELETE where the return value is the number of rows affected
+ // for the rest of the commands the return value is -1.
+ if ((CommandText.ToUpper().IndexOf("UPDATE")!=-1) ||
+ (CommandText.ToUpper().IndexOf("INSERT")!=-1) ||
+ (CommandText.ToUpper().IndexOf("DELETE")!=-1))
+ ret = Connection.Tds.RecordsAffected;
+ else
+ ret = -1;
+ }
+ GetOutputParameters ();
+ ( (SqlAsyncResult) ar).Ended = true;
+ return ret;
+ }
+
+ public IAsyncResult BeginExecuteReader ()
+ {
+ return BeginExecuteReader (null, null, CommandBehavior.Default);
+ }
+
+ public IAsyncResult BeginExecuteReader (CommandBehavior behavior)
+ {
+ return BeginExecuteReader (null, null, behavior);
+ }
+
+ public IAsyncResult BeginExecuteReader (AsyncCallback callback, object state)
+ {
+ return BeginExecuteReader (callback, state, CommandBehavior.Default);
+ }
+
+ public IAsyncResult BeginExecuteReader (AsyncCallback callback, object state, CommandBehavior behavior)
+ {
+ ValidateCommand ("BeginExecuteReader");
+ this.behavior = behavior;
+ SqlAsyncResult ar = new SqlAsyncResult (callback, state);
+ ar.EndMethod = "EndExecuteReader";
+ IAsyncResult tdsResult = BeginExecuteInternal (behavior, true,
+ ar.BubbleCallback, state);
+ ar.InternalResult = tdsResult;
+ return ar;
+ }
+
+ public SqlDataReader EndExecuteReader (IAsyncResult ar)
+ {
+ ValidateAsyncResult (ar, "EndExecuteReader");
+ EndExecuteInternal (ar);
+ SqlDataReader reader = null;
+ try {
+ reader = new SqlDataReader (this);
+ }
+ catch (TdsTimeoutException e) {
+ // if behavior is closeconnection, even if it throws exception
+ // the connection has to be closed.
+ if ((behavior & CommandBehavior.CloseConnection) != 0)
+ Connection.Close ();
+ throw SqlException.FromTdsInternalException ((TdsInternalException) e);
+ } catch (SqlException) {
+ // if behavior is closeconnection, even if it throws exception
+ // the connection has to be closed.
+ if ((behavior & CommandBehavior.CloseConnection) != 0)
+ Connection.Close ();
+
+ throw;
+ }
+
+ ( (SqlAsyncResult) ar).Ended = true;
+ return reader;
+ }
+
+ public IAsyncResult BeginExecuteXmlReader (AsyncCallback callback, object state)
+ {
+ ValidateCommand ("BeginExecuteXmlReader");
+ SqlAsyncResult ar = new SqlAsyncResult (callback, state);
+ ar.EndMethod = "EndExecuteXmlReader";
+ ar.InternalResult = BeginExecuteInternal (behavior, true,
+ ar.BubbleCallback, state);
+ return ar;
+ }
+
+ public XmlReader EndExecuteXmlReader (IAsyncResult ar)
+ {
+ ValidateAsyncResult (ar, "EndExecuteXmlReader");
+ EndExecuteInternal (ar);
+ SqlDataReader reader = new SqlDataReader (this);
+ SqlXmlTextReader textReader = new SqlXmlTextReader (reader);
+ XmlReader xmlReader = new XmlTextReader (textReader);
+ ( (SqlAsyncResult) ar).Ended = true;
+ return xmlReader;
+ }
+
+
+ internal void ValidateAsyncResult (IAsyncResult ar, string endMethod)
+ {
+ if (ar == null)
+ throw new ArgumentException ("result passed is null!");
+ if (! (ar is SqlAsyncResult))
+ throw new ArgumentException (String.Format ("cannot test validity of types {0}",
+ ar.GetType ()
+ ));
+ SqlAsyncResult result = (SqlAsyncResult) ar;
+
+ if (result.EndMethod != endMethod)
+ throw new InvalidOperationException (String.Format ("Mismatched {0} called for AsyncResult. " +
+ "Expected call to {1} but {0} is called instead.",
+ endMethod,
+ result.EndMethod
+ ));
+ if (result.Ended)
+ throw new InvalidOperationException (String.Format ("The method {0} cannot be called " +
+ "more than once for the same AsyncResult.",
+ endMethod));
+
+ }
+
+ #endregion // Asynchronous Methods
+#endif // NET_2_0
}
}
diff --git a/mcs/class/System.Data/System.Data.SqlClient/SqlConnection.cs b/mcs/class/System.Data/System.Data.SqlClient/SqlConnection.cs
index e8e223d8e4f..e603d6671e4 100644
--- a/mcs/class/System.Data/System.Data.SqlClient/SqlConnection.cs
+++ b/mcs/class/System.Data/System.Data.SqlClient/SqlConnection.cs
@@ -719,6 +719,11 @@ namespace System.Data.SqlClient {
parameters["POOLING"] = "true";
if (null == parameters.Get ("WORKSTATION ID") && null == parameters.Get ("WSID"))
parameters["WORKSTATION ID"] = Dns.GetHostName();
+#if NET_2_0
+ if (null == parameters.Get ("ASYNC") &&
+ null == parameters.Get ("ASYNCHRONOUS PROCESSING"))
+ parameters ["ASYNCHRONOUS PROCESSING"] = "false";
+#endif
}
private void SetProperties (NameValueCollection parameters)
@@ -789,6 +794,10 @@ namespace System.Data.SqlClient {
#if NET_2_0
case "MULTIPLEACTIVERESULTSETS":
break;
+ case "ASYNCHRONOUS PROCESSING" :
+ case "ASYNC" :
+ async = ConvertToBoolean (name, value);
+ break;
#endif
case "NET" :
case "NETWORK" :
@@ -918,5 +927,25 @@ namespace System.Data.SqlClient {
}
#endregion // Methods
+
+#if NET_2_0
+ #region Fields Net 2
+
+ bool async = false;
+
+ #endregion // Fields Net 2
+
+ #region Properties Net 2
+
+ [DataSysDescription ("Enable Asynchronous processing, 'Asynchrouse Processing=true/false' in the ConnectionString.")]
+ [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+ internal bool AsyncProcessing {
+ get { return async; }
+ }
+
+ #endregion // Properties Net 2
+
+#endif // NET_2_0
+
}
}