2 // Mono.Data.Tds.Protocol.Tds70.cs
5 // Tim Coleman (tim@timcoleman.com)
6 // Diego Caravana (diego@toth.it)
7 // Sebastien Pouliot (sebastien@ximian.com)
8 // Daniel Morgan (danielmorgan@verizon.net)
9 // Gert Driesen (drieseng@users.sourceforge.net)
11 // Copyright (C) 2002 Tim Coleman
12 // Portions (C) 2003 Motus Technologies Inc. (http://www.motus.com)
13 // Portions (C) 2003 Daniel Morgan
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 using System.Globalization;
40 using Mono.Security.Protocol.Ntlm;
42 namespace Mono.Data.Tds.Protocol
44 public sealed class Tds70 : Tds
48 public readonly static TdsVersion Version = TdsVersion.tds70;
49 static readonly decimal SMALLMONEY_MIN = -214748.3648m;
50 static readonly decimal SMALLMONEY_MAX = 214748.3647m;
56 public Tds70 (string server, int port)
57 : this (server, port, 512, 15)
61 public Tds70 (string server, int port, int packetSize, int timeout)
62 : base (server, port, packetSize, timeout, Version)
66 #endregion // Constructors
70 private string BuildExec (string sql)
72 string esql = sql.Replace ("'", "''"); // escape single quote
73 if (Parameters != null && Parameters.Count > 0)
74 return BuildProcedureCall (String.Format ("sp_executesql N'{0}', N'{1}', ", esql, BuildPreparedParameters ()));
76 return BuildProcedureCall (String.Format ("sp_executesql N'{0}'", esql));
79 private string BuildParameters ()
81 if (Parameters == null || Parameters.Count == 0)
84 StringBuilder result = new StringBuilder ();
85 foreach (TdsMetaParameter p in Parameters) {
86 string parameterName = p.ParameterName;
87 if (parameterName [0] == '@') {
88 parameterName = parameterName.Substring (1);
90 if (p.Direction != TdsParameterDirection.ReturnValue) {
91 if (result.Length > 0)
93 if (p.Direction == TdsParameterDirection.InputOutput)
94 result.AppendFormat ("@{0}={0} output", parameterName);
96 result.Append (FormatParameter (p));
99 return result.ToString ();
102 private string BuildPreparedParameters ()
104 StringBuilder parms = new StringBuilder ();
105 foreach (TdsMetaParameter p in Parameters) {
106 if (parms.Length > 0)
108 parms.Append (p.Prepare ());
109 if (p.Direction == TdsParameterDirection.Output)
110 parms.Append (" output");
112 return parms.ToString ();
115 private string BuildPreparedQuery (string id)
117 return BuildProcedureCall (String.Format ("sp_execute {0},", id));
120 private string BuildProcedureCall (string procedure)
122 string exec = String.Empty;
124 StringBuilder declare = new StringBuilder ();
125 StringBuilder select = new StringBuilder ();
126 StringBuilder set = new StringBuilder ();
129 if (Parameters != null) {
130 foreach (TdsMetaParameter p in Parameters) {
131 string parameterName = p.ParameterName;
132 if (parameterName [0] == '@') {
133 parameterName = parameterName.Substring (1);
136 if (p.Direction != TdsParameterDirection.Input) {
138 select.Append ("select ");
140 select.Append (", ");
141 select.Append ("@" + parameterName);
143 declare.Append (String.Format ("declare {0}\n", p.Prepare ()));
145 if (p.Direction != TdsParameterDirection.ReturnValue) {
146 if (p.Direction == TdsParameterDirection.InputOutput)
147 set.Append (String.Format ("set {0}\n", FormatParameter(p)));
149 set.Append (String.Format ("set @{0}=NULL\n", parameterName));
154 if (p.Direction == TdsParameterDirection.ReturnValue)
155 exec = "@" + parameterName + "=";
158 exec = "exec " + exec;
160 return String.Format ("{0}{1}{2}{3} {4}\n{5}",
161 declare.ToString (), set.ToString (), exec,
162 procedure, BuildParameters (), select.ToString ());
165 public override bool Connect (TdsConnectionParameters connectionParameters)
168 throw new InvalidOperationException ("The connection is already open.");
170 connectionParms = connectionParameters;
172 SetLanguage (connectionParameters.Language);
173 SetCharset ("utf-8");
175 byte[] empty = new byte[0];
179 byte[] domainMagic = { 6, 0x7d, 0x0f, 0xfd, 0xff, 0x0, 0x0, 0x0,
180 0x0, 0xe0, 0x83, 0x0, 0x0,
181 0x68, 0x01, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00 };
182 byte[] sqlserverMagic = { 6, 0x0, 0x0, 0x0,
184 0x0, 0xe0, 0x03, 0x0,
185 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
189 if (connectionParameters.DomainLogin)
192 magic = sqlserverMagic;
194 string username = connectionParameters.User;
195 string domain = null;
197 int idx = username.IndexOf ("\\");
199 domain = username.Substring (0, idx);
200 username = username.Substring (idx + 1);
202 connectionParameters.DefaultDomain = domain;
203 connectionParameters.User = username;
205 domain = Environment.UserDomainName;
206 connectionParameters.DefaultDomain = domain;
209 short partialPacketSize = (short) (86 + (
210 connectionParameters.Hostname.Length +
211 connectionParameters.ApplicationName.Length +
213 connectionParameters.LibraryName.Length +
215 connectionParameters.Database.Length +
216 connectionParameters.AttachDBFileName.Length) * 2);
218 if (connectionParameters.DomainLogin) {
219 authLen = ((short) (32 + (connectionParameters.Hostname.Length +
221 partialPacketSize += authLen;
223 partialPacketSize += ((short) ((username.Length + connectionParameters.Password.Length) * 2));
225 int totalPacketSize = partialPacketSize;
227 Comm.StartPacket (TdsPacketType.Logon70);
229 Comm.Append (totalPacketSize);
231 //Comm.Append (empty, 3, pad);
232 byte[] version = {0x00, 0x0, 0x0, 0x70};
233 Comm.Append (version); // TDS Version 7
234 Comm.Append ((int)this.PacketSize); // Set the Block Size
235 Comm.Append (empty, 3, pad);
241 Comm.Append (curPos);
242 Comm.Append ((short) connectionParameters.Hostname.Length);
243 curPos += (short) (connectionParameters.Hostname.Length * 2);
245 if (connectionParameters.DomainLogin) {
246 Comm.Append((short)0);
247 Comm.Append((short)0);
248 Comm.Append((short)0);
249 Comm.Append((short)0);
252 Comm.Append (curPos);
253 Comm.Append ((short) username.Length);
254 curPos += ((short) (username.Length * 2));
257 Comm.Append (curPos);
258 Comm.Append ((short) connectionParameters.Password.Length);
259 curPos += (short) (connectionParameters.Password.Length * 2);
263 Comm.Append (curPos);
264 Comm.Append ((short) connectionParameters.ApplicationName.Length);
265 curPos += (short) (connectionParameters.ApplicationName.Length * 2);
268 Comm.Append (curPos);
269 Comm.Append ((short) DataSource.Length);
270 curPos += (short) (DataSource.Length * 2);
273 Comm.Append ((short) curPos);
274 Comm.Append ((short) 0);
277 Comm.Append (curPos);
278 Comm.Append ((short) connectionParameters.LibraryName.Length);
279 curPos += (short) (connectionParameters.LibraryName.Length * 2);
282 Comm.Append (curPos);
283 Comm.Append ((short) Language.Length);
284 curPos += (short) (Language.Length * 2);
287 Comm.Append (curPos);
288 Comm.Append ((short) connectionParameters.Database.Length);
289 curPos += (short) (connectionParameters.Database.Length * 2);
292 Comm.Append((byte) 0);
293 Comm.Append((byte) 0);
294 Comm.Append((byte) 0);
295 Comm.Append((byte) 0);
296 Comm.Append((byte) 0);
297 Comm.Append((byte) 0);
299 // Authentication Stuff
300 Comm.Append ((short) curPos);
301 if (connectionParameters.DomainLogin) {
302 Comm.Append ((short) authLen);
303 curPos += (short) authLen;
305 Comm.Append ((short) 0);
308 Comm.Append (curPos);
309 Comm.Append ((short)( connectionParameters.AttachDBFileName.Length));
310 curPos += (short)(connectionParameters.AttachDBFileName.Length*2);
312 // Connection Parameters
313 Comm.Append (connectionParameters.Hostname);
314 if (!connectionParameters.DomainLogin) {
315 // SQL Server Authentication
316 Comm.Append (connectionParameters.User);
317 string scrambledPwd = EncryptPassword (connectionParameters.Password);
318 Comm.Append (scrambledPwd);
320 Comm.Append (connectionParameters.ApplicationName);
321 Comm.Append (DataSource);
322 Comm.Append (connectionParameters.LibraryName);
323 Comm.Append (Language);
324 Comm.Append (connectionParameters.Database);
326 if (connectionParameters.DomainLogin) {
327 // the rest of the packet is NTLMSSP authentication
328 Type1Message msg = new Type1Message ();
330 msg.Host = connectionParameters.Hostname;
331 msg.Flags = NtlmFlags.NegotiateUnicode |
332 NtlmFlags.NegotiateNtlm |
333 NtlmFlags.NegotiateDomainSupplied |
334 NtlmFlags.NegotiateWorkstationSupplied |
335 NtlmFlags.NegotiateAlwaysSign; // 0xb201
336 Comm.Append (msg.GetBytes ());
339 Comm.Append (connectionParameters.AttachDBFileName);
347 private static string EncryptPassword (string pass)
349 int xormask = 0x5a5a;
350 int len = pass.Length;
351 char[] chars = new char[len];
353 for (int i = 0; i < len; ++i) {
354 int c = ((int) (pass[i])) ^ xormask;
355 int m1 = (c >> 4) & 0x0f0f;
356 int m2 = (c << 4) & 0xf0f0;
357 chars[i] = (char) (m1 | m2);
360 return new String (chars);
363 public override bool Reset ()
365 // Check validity of the connection - a false removes
366 // the connection from the pool
367 // NOTE: MS implementation will throw a connection-reset error as it will
368 // try to use the same connection
369 if (!Comm.IsConnected ())
372 // Set "reset-connection" bit for the next message packet
373 Comm.ResetConnection = true;
378 public override void ExecPrepared (string commandText, TdsMetaParameterCollection parameters, int timeout, bool wantResults)
380 Parameters = parameters;
381 ExecuteQuery (BuildPreparedQuery (commandText), timeout, wantResults);
384 public override void ExecProc (string commandText, TdsMetaParameterCollection parameters, int timeout, bool wantResults)
386 Parameters = parameters;
387 ExecRPC (commandText, parameters, timeout, wantResults);
390 protected override void ExecRPC (string rpcName, TdsMetaParameterCollection parameters,
391 int timeout, bool wantResults)
395 Comm.StartPacket (TdsPacketType.RPC);
397 Comm.Append ( (short) rpcName.Length);
398 Comm.Append (rpcName);
399 Comm.Append ( (short) 0); //no meta data
400 if (parameters != null) {
401 foreach (TdsMetaParameter param in parameters) {
402 if (param.Direction == TdsParameterDirection.ReturnValue)
404 string pname = param.ParameterName;
405 if (pname != null && pname.Length > 0 && pname [0] == '@') {
406 Comm.Append ( (byte) pname.Length);
409 Comm.Append ( (byte) (pname.Length + 1));
410 Comm.Append ("@" + pname);
412 short status = 0; // unused
413 if (param.Direction != TdsParameterDirection.Input)
414 status |= 0x01; // output
415 Comm.Append ( (byte) status);
416 WriteParameterInfo (param);
420 CheckForData (timeout);
425 private void WriteParameterInfo (TdsMetaParameter param)
428 Ms.net send non-nullable datatypes as nullable and allows setting null values
429 to int/float etc.. So, using Nullable form of type for all data
431 param.IsNullable = true;
432 TdsColumnType colType = param.GetMetaType ();
433 param.IsNullable = false;
435 Comm.Append ((byte)colType); // type
437 int size = param.Size;
439 size = param.GetActualSize ();
442 If column type is SqlDbType.NVarChar the size of parameter is multiplied by 2
443 FIXME: Need to check for other types
445 if (colType == TdsColumnType.BigNVarChar)
447 if (IsLargeType (colType))
448 Comm.Append ((short)size); // Parameter size passed in SqlParameter
449 else if (IsBlobType (colType))
450 Comm.Append (size); // Parameter size passed in SqlParameter
452 Comm.Append ((byte)size);
454 // Precision and Scale are non-zero for only decimal/numeric
455 if ( param.TypeName == "decimal" || param.TypeName == "numeric") {
456 Comm.Append ((param.Precision !=0 ) ? param.Precision : (byte) 28);
457 Comm.Append (param.Scale);
460 size = param.GetActualSize ();
461 if (IsLargeType (colType))
462 Comm.Append ((short)size);
463 else if (IsBlobType (colType))
466 Comm.Append ((byte)size);
469 switch (param.TypeName) {
471 Decimal val = (decimal) param.Value;
472 int[] arr = Decimal.GetBits (val);
475 Comm.Append (arr[1]);
476 Comm.Append (arr[0]);
478 Comm.Append (~arr[1]);
479 Comm.Append (~arr[0] + 1);
484 Decimal val = (decimal) param.Value;
485 if (val < SMALLMONEY_MIN || val > SMALLMONEY_MAX)
486 throw new OverflowException (string.Format (
487 CultureInfo.InvariantCulture,
488 "Value '{0}' is not valid for SmallMoney."
489 + " Must be between {1:N4} and {2:N4}.",
493 val.ToString (CultureInfo.CurrentCulture),
495 SMALLMONEY_MIN, SMALLMONEY_MAX));
497 int[] arr = Decimal.GetBits (val);
498 int sign = (val>0 ? 1: -1);
499 Comm.Append (sign * arr[0]);
503 Comm.Append ((DateTime)param.Value, 8);
505 case "smalldatetime":
506 Comm.Append ((DateTime)param.Value, 4);
514 byte [] tmp = param.GetBytes ();
517 case "uniqueidentifier" :
518 Comm.Append (((Guid)param.Value).ToByteArray());
521 Comm.Append (param.Value);
528 public override void Execute (string commandText, TdsMetaParameterCollection parameters, int timeout, bool wantResults)
530 Parameters = parameters;
531 string sql = commandText;
532 if (wantResults || (Parameters != null && Parameters.Count > 0))
533 sql = BuildExec (commandText);
534 ExecuteQuery (sql, timeout, wantResults);
537 private string FormatParameter (TdsMetaParameter parameter)
539 string parameterName = parameter.ParameterName;
540 if (parameterName [0] == '@') {
541 parameterName = parameterName.Substring (1);
543 if (parameter.Direction == TdsParameterDirection.Output)
544 return String.Format ("@{0}={0} output", parameterName);
545 if (parameter.Value == null || parameter.Value == DBNull.Value)
546 return String.Format ("@{0}=NULL", parameterName);
549 switch (parameter.TypeName) {
550 case "smalldatetime":
552 DateTime d = Convert.ToDateTime (parameter.Value);
553 value = String.Format (base.Locale,
554 "'{0:MMM dd yyyy hh:mm:ss.fff tt}'", d);
565 object paramValue = parameter.Value;
566 Type paramType = paramValue.GetType ();
567 if (paramType.IsEnum)
568 paramValue = Convert.ChangeType (paramValue,
569 Type.GetTypeCode (paramType));
570 value = paramValue.ToString ();
574 value = String.Format ("N'{0}'", parameter.Value.ToString ().Replace ("'", "''"));
576 case "uniqueidentifier":
577 value = String.Format ("'{0}'", ((Guid) parameter.Value).ToString (string.Empty));
580 if (parameter.Value.GetType () == typeof (bool))
581 value = (((bool) parameter.Value) ? "0x1" : "0x0");
583 value = parameter.Value.ToString ();
588 byte[] byteArray = (byte[]) parameter.Value;
589 // In 1.0 profile, BitConverter.ToString() throws ArgumentOutOfRangeException when passed a 0-length
590 // array, so handle that as a special case.
591 if (byteArray.Length == 0)
594 value = String.Format ("0x{0}", BitConverter.ToString (byteArray).Replace ("-", string.Empty).ToLower ());
597 value = String.Format ("'{0}'", parameter.Value.ToString ().Replace ("'", "''"));
601 return "@" + parameterName + "=" + value;
604 public override string Prepare (string commandText, TdsMetaParameterCollection parameters)
606 Parameters = parameters;
608 TdsMetaParameterCollection parms = new TdsMetaParameterCollection ();
609 TdsMetaParameter parm = new TdsMetaParameter ("@Handle", "int", null);
610 parm.Direction = TdsParameterDirection.Output;
613 parms.Add (new TdsMetaParameter ("@VarDecl", "nvarchar", BuildPreparedParameters ()));
614 parms.Add (new TdsMetaParameter ("@Query", "nvarchar", commandText));
616 ExecProc ("sp_prepare", parms, 0, true);
618 return OutputParameters[0].ToString () ;
619 //if (ColumnValues == null || ColumnValues [0] == null || ColumnValues [0] == DBNull.Value)
620 // throw new TdsInternalException ();
621 //return string.Empty;
622 //return ColumnValues [0].ToString ();
625 protected override TdsDataColumnCollection ProcessColumnInfo ()
627 TdsDataColumnCollection result = new TdsDataColumnCollection ();
628 int numColumns = Comm.GetTdsShort ();
629 for (int i = 0; i < numColumns; i += 1) {
630 byte[] flagData = new byte[4];
631 for (int j = 0; j < 4; j += 1)
632 flagData[j] = Comm.GetByte ();
634 bool nullable = (flagData[2] & 0x01) > 0;
635 //bool caseSensitive = (flagData[2] & 0x02) > 0;
636 bool writable = (flagData[2] & 0x0c) > 0;
637 bool autoIncrement = (flagData[2] & 0x10) > 0;
638 bool isIdentity = (flagData[2] & 0x10) > 0;
640 TdsColumnType columnType = (TdsColumnType) ((Comm.GetByte () & 0xff));
642 byte xColumnType = 0;
643 if (IsLargeType (columnType)) {
644 xColumnType = (byte) columnType;
645 if (columnType != TdsColumnType.NChar)
650 string tableName = null;
652 if (IsBlobType (columnType)) {
653 columnSize = Comm.GetTdsInt ();
654 tableName = Comm.GetString (Comm.GetTdsShort ());
655 } else if (IsFixedSizeColumn (columnType))
656 columnSize = LookupBufferSize (columnType);
657 else if (IsLargeType ((TdsColumnType) xColumnType))
658 columnSize = Comm.GetTdsShort ();
660 columnSize = Comm.GetByte () & 0xff;
662 if (IsWideType ((TdsColumnType) columnType))
668 if (columnType == TdsColumnType.Decimal || columnType == TdsColumnType.Numeric) {
669 precision = Comm.GetByte ();
670 scale = Comm.GetByte ();
672 precision = GetPrecision (columnType, columnSize);
673 scale = GetScale (columnType, columnSize);
676 string columnName = Comm.GetString (Comm.GetByte ());
678 TdsDataColumn col = new TdsDataColumn ();
681 col.ColumnType = columnType;
682 col.ColumnName = columnName;
683 col.IsAutoIncrement = autoIncrement;
684 col.IsIdentity = isIdentity;
685 col.ColumnSize = columnSize;
686 col.NumericPrecision = precision;
687 col.NumericScale = scale;
688 col.IsReadOnly = !writable;
689 col.AllowDBNull = nullable;
690 col.BaseTableName = tableName;
692 col ["ColumnType"] = columnType;
693 col ["ColumnName"] = columnName;
694 col ["IsAutoIncrement"] = autoIncrement;
695 col ["IsIdentity"] = isIdentity;
696 col ["ColumnSize"] = columnSize;
697 col ["NumericPrecision"] = precision;
698 col ["NumericScale"] = scale;
699 col ["IsReadOnly"] = !writable;
700 col ["AllowDBNull"] = nullable;
701 col ["BaseTableName"] = tableName;
707 public override void Unprepare (string statementId)
709 TdsMetaParameterCollection parms = new TdsMetaParameterCollection ();
710 parms.Add (new TdsMetaParameter ("@P1", "int", Int32.Parse (statementId)));
711 ExecProc ("sp_unprepare", parms, 0, false);
714 protected override bool IsValidRowCount (byte status, byte op)
716 if ((status & (byte)0x10) == 0 || op == (byte)0xc1)
721 protected override void ProcessReturnStatus ()
723 int result = Comm.GetTdsInt ();
724 if (Parameters != null) {
725 foreach (TdsMetaParameter param in Parameters) {
726 if (param.Direction == TdsParameterDirection.ReturnValue) {
727 param.Value = result;
734 byte GetScale (TdsColumnType type, int columnSize)
737 case TdsColumnType.DateTime:
739 case TdsColumnType.DateTime4:
741 case TdsColumnType.DateTimeN:
742 switch (columnSize) {
753 throw new NotSupportedException (string.Format (
754 CultureInfo.InvariantCulture,
755 "Fixed scale not defined for column " +
756 "type '{0}' with size {1}.", type, columnSize));
759 byte GetPrecision (TdsColumnType type, int columnSize)
762 case TdsColumnType.Binary:
764 case TdsColumnType.Bit:
766 case TdsColumnType.Char:
768 case TdsColumnType.DateTime:
770 case TdsColumnType.DateTime4:
772 case TdsColumnType.DateTimeN:
773 switch (columnSize) {
780 case TdsColumnType.Real:
782 case TdsColumnType.Float8:
784 case TdsColumnType.FloatN:
785 switch (columnSize) {
792 case TdsColumnType.Image:
794 case TdsColumnType.Int1:
796 case TdsColumnType.Int2:
798 case TdsColumnType.Int4:
800 case TdsColumnType.IntN:
801 switch (columnSize) {
810 case TdsColumnType.Void:
812 case TdsColumnType.Text:
814 case TdsColumnType.UniqueIdentifier:
816 case TdsColumnType.VarBinary:
818 case TdsColumnType.VarChar:
820 case TdsColumnType.Money:
822 case TdsColumnType.NText:
824 case TdsColumnType.NVarChar:
826 case TdsColumnType.BitN:
828 case TdsColumnType.MoneyN:
829 switch (columnSize) {
836 case TdsColumnType.Money4:
838 case TdsColumnType.NChar:
840 case TdsColumnType.BigBinary:
842 case TdsColumnType.BigVarBinary:
844 case TdsColumnType.BigVarChar:
846 case TdsColumnType.BigNVarChar:
848 case TdsColumnType.BigChar:
850 case TdsColumnType.SmallMoney:
852 case TdsColumnType.Variant:
854 case TdsColumnType.BigInt:
858 throw new NotSupportedException (string.Format (
859 CultureInfo.InvariantCulture,
860 "Fixed precision not defined for column " +
861 "type '{0}' with size {1}.", type, columnSize));
864 #endregion // Methods
867 #region Asynchronous Methods
869 public override IAsyncResult BeginExecuteNonQuery (string cmdText,
870 TdsMetaParameterCollection parameters,
871 AsyncCallback callback,
874 Parameters = parameters;
875 string sql = cmdText;
876 if (Parameters != null && Parameters.Count > 0)
877 sql = BuildExec (cmdText);
879 IAsyncResult ar = BeginExecuteQueryInternal (sql, false, callback, state);
883 public override void EndExecuteNonQuery (IAsyncResult ar)
885 EndExecuteQueryInternal (ar);
888 public override IAsyncResult BeginExecuteQuery (string cmdText,
889 TdsMetaParameterCollection parameters,
890 AsyncCallback callback,
893 Parameters = parameters;
894 string sql = cmdText;
895 if (Parameters != null && Parameters.Count > 0)
896 sql = BuildExec (cmdText);
898 IAsyncResult ar = BeginExecuteQueryInternal (sql, true, callback, state);
902 public override void EndExecuteQuery (IAsyncResult ar)
904 EndExecuteQueryInternal (ar);
907 public override IAsyncResult BeginExecuteProcedure (string prolog,
911 TdsMetaParameterCollection parameters,
912 AsyncCallback callback,
915 Parameters = parameters;
916 string pcall = BuildProcedureCall (cmdText);
917 string sql = String.Format ("{0};{1};{2};", prolog, pcall, epilog);
919 IAsyncResult ar = BeginExecuteQueryInternal (sql, !IsNonQuery, callback, state);
923 public override void EndExecuteProcedure (IAsyncResult ar)
925 EndExecuteQueryInternal (ar);
928 #endregion // Asynchronous Methods