2 // Mono.Data.SybaseClient.SybaseCommand.cs
5 // Rodrigo Moya (rodrigo@ximian.com)
6 // Daniel Morgan (danmorg@sc.rr.com)
7 // Tim Coleman (tim@timcoleman.com)
9 // (C) Ximian, Inc 2002 http://www.ximian.com/
10 // (C) Daniel Morgan, 2002
11 // Copyright (C) Tim Coleman, 2002
14 using Mono.Data.TdsClient.Internal;
16 using System.Collections.Specialized;
17 using System.ComponentModel;
19 using System.Data.Common;
20 using System.Runtime.InteropServices;
24 namespace Mono.Data.SybaseClient {
25 public sealed class SybaseCommand : Component, IDbCommand, ICloneable
30 bool designTimeVisible;
33 CommandType commandType;
34 SybaseConnection connection;
35 SybaseTransaction transaction;
37 SybaseParameterCollection parameters = new SybaseParameterCollection ();
38 private CommandBehavior behavior = CommandBehavior.Default;
40 NameValueCollection procedureCache = new NameValueCollection ();
46 public SybaseCommand()
47 : this (String.Empty, null, null)
51 public SybaseCommand (string commandText)
52 : this (commandText, null, null)
54 commandText = commandText;
57 public SybaseCommand (string commandText, SybaseConnection connection)
58 : this (commandText, connection, null)
60 Connection = connection;
63 public SybaseCommand (string commandText, SybaseConnection connection, SybaseTransaction transaction)
65 this.commandText = commandText;
66 this.connection = connection;
67 this.transaction = transaction;
68 this.commandType = CommandType.Text;
69 this.designTimeVisible = false;
70 this.commandTimeout = 30;
73 #endregion // Constructors
77 internal CommandBehavior CommandBehavior {
78 get { return behavior; }
81 public string CommandText {
82 get { return CommandText; }
83 set { commandText = value; }
86 public int CommandTimeout {
87 get { return commandTimeout; }
89 if (commandTimeout < 0)
90 throw new ArgumentException ("The property value assigned is less than 0.");
91 commandTimeout = value;
95 public CommandType CommandType {
96 get { return commandType; }
97 [MonoTODO ("Validate")]
98 set { commandType = value; }
101 public SybaseConnection Connection {
102 get { return connection; }
104 if (transaction != null && connection.Transaction != null && connection.Transaction.IsOpen)
105 throw new InvalidOperationException ("The Connection property was changed while a transaction was in progress.");
111 public bool DesignTimeVisible {
112 get { return designTimeVisible; }
113 set { designTimeVisible = value; }
116 public SybaseParameterCollection Parameters {
117 get { return parameters; }
121 get { return connection.Tds; }
124 IDbConnection IDbCommand.Connection {
125 get { return Connection; }
127 if (!(value is SybaseConnection))
128 throw new InvalidCastException ("The value was not a valid SybaseConnection.");
129 Connection = (SybaseConnection) value;
133 IDataParameterCollection IDbCommand.Parameters {
134 get { return Parameters; }
137 IDbTransaction IDbCommand.Transaction {
138 get { return Transaction; }
140 if (!(value is SybaseTransaction))
141 throw new ArgumentException ();
142 Transaction = (SybaseTransaction) value;
146 public SybaseTransaction Transaction {
147 get { return transaction; }
148 set { transaction = value; }
152 public UpdateRowSource UpdatedRowSource {
153 get { throw new NotImplementedException (); }
154 set { throw new NotImplementedException (); }
161 public void Cancel ()
163 if (connection == null || connection.Tds == null)
165 connection.Tds.Cancel ();
166 connection.CheckForErrors ();
169 internal void CloseDataReader (bool moreResults)
172 moreResults = connection.Tds.NextResult ();
174 if (connection.Tds.OutputParameters.Count > 0) {
176 foreach (SybaseParameter parameter in parameters) {
177 if (parameter.Direction != ParameterDirection.Input)
178 parameter.Value = connection.Tds.OutputParameters[index];
180 if (index >= connection.Tds.OutputParameters.Count)
184 connection.DataReaderOpen = false;
185 if ((behavior & CommandBehavior.CloseConnection) != 0)
189 public SybaseParameter CreateParameter ()
191 return new SybaseParameter ();
194 public int ExecuteNonQuery ()
196 int result = connection.Tds.ExecuteNonQuery (ValidateQuery ("ExecuteNonQuery"));
197 connection.CheckForErrors ();
201 public SybaseDataReader ExecuteReader ()
203 return ExecuteReader (CommandBehavior.Default);
206 public SybaseDataReader ExecuteReader (CommandBehavior behavior)
208 this.behavior = behavior;
209 connection.Tds.ExecuteQuery (ValidateQuery ("ExecuteReader"));
210 connection.CheckForErrors ();
211 connection.DataReaderOpen = true;
212 return new SybaseDataReader (this);
215 public object ExecuteScalar ()
217 connection.Tds.ExecuteQuery (ValidateQuery ("ExecuteScalar"));
219 bool moreResults = connection.Tds.NextResult ();
220 connection.CheckForErrors ();
225 moreResults = connection.Tds.NextRow ();
226 connection.CheckForErrors ();
231 object result = connection.Tds.ColumnValues[0];
232 CloseDataReader (true);
236 static string FormatParameter (SybaseParameter parameter)
238 if (parameter.Value == null)
241 switch (parameter.SybaseType) {
242 case SybaseType.BigInt :
243 case SybaseType.Bit :
244 case SybaseType.Decimal :
245 case SybaseType.Float :
246 case SybaseType.Int :
247 case SybaseType.Money :
248 case SybaseType.Real :
249 case SybaseType.SmallInt :
250 case SybaseType.SmallMoney :
251 case SybaseType.TinyInt :
252 return parameter.Value.ToString ();
254 return String.Format ("'{0}'", parameter.Value.ToString ().Replace ("'", "''"));
258 static string FormatQuery (string commandText, CommandType commandType, SybaseParameterCollection parameters)
260 StringBuilder result = new StringBuilder ();
262 switch (commandType) {
263 case CommandType.Text :
265 case CommandType.TableDirect :
266 return String.Format ("SELECT * FROM {0}", commandText);
267 case CommandType.StoredProcedure :
269 StringBuilder parms = new StringBuilder ();
270 StringBuilder declarations = new StringBuilder ();
272 foreach (SybaseParameter parameter in parameters) {
273 switch (parameter.Direction) {
274 case ParameterDirection.Input :
275 if (parms.Length > 0)
277 parms.Append (FormatParameter (parameter));
279 case ParameterDirection.Output :
280 if (parms.Length > 0)
282 parms.Append (parameter.ParameterName);
283 parms.Append (" OUT");
285 if (declarations.Length == 0)
286 declarations.Append ("DECLARE ");
288 declarations.Append (",");
290 declarations.Append (parameter.Prepare ());
293 throw new NotImplementedException ("Only support input and output parameters.");
296 result.Append (declarations.ToString ());
297 result.Append (" EXEC ");
298 result.Append (commandText);
300 result.Append (parms);
301 return result.ToString ();
303 throw new InvalidOperationException ("The CommandType was not recognized.");
308 object ICloneable.Clone ()
310 throw new NotImplementedException ();
313 IDbDataParameter IDbCommand.CreateParameter ()
315 return CreateParameter ();
318 IDataReader IDbCommand.ExecuteReader ()
320 return ExecuteReader ();
323 IDataReader IDbCommand.ExecuteReader (CommandBehavior behavior)
325 return ExecuteReader (behavior);
328 void IDisposable.Dispose ()
333 public void Prepare ()
335 bool prependComma = false;
336 Guid uniqueId = Guid.NewGuid ();
337 string procedureName = String.Format ("#mono#{0}", uniqueId.ToString ("N"));
338 StringBuilder procedureString = new StringBuilder ();
340 procedureString.Append ("CREATE PROC ");
341 procedureString.Append (procedureName);
342 procedureString.Append (" (");
344 foreach (SybaseParameter parameter in parameters) {
346 procedureString.Append (", ");
349 procedureString.Append (parameter.Prepare ());
350 if (parameter.Direction == ParameterDirection.Output)
351 procedureString.Append (" OUT");
354 procedureString.Append (") AS ");
355 procedureString.Append (commandText);
356 string cmdText = FormatQuery (procedureName, CommandType.StoredProcedure, parameters);
357 connection.Tds.ExecuteNonQuery (procedureString.ToString ());
358 procedureCache[commandText] = cmdText;
361 public void ResetCommandTimeout ()
366 string ValidateQuery (string methodName)
368 if (connection == null)
369 throw new InvalidOperationException (String.Format ("{0} requires a Connection object to continue.", methodName));
370 if (connection.Transaction != null && transaction != connection.Transaction)
371 throw new InvalidOperationException ("The Connection object does not have the same transaction as the command object.");
372 if (connection.State != ConnectionState.Open)
373 throw new InvalidOperationException (String.Format ("ExecuteNonQuery requires an open Connection object to continue. This connection is closed.", methodName));
374 if (commandText == String.Empty || commandText == null)
375 throw new InvalidOperationException ("The command text for this Command has not been set.");
377 string sql = procedureCache[commandText];
379 sql = FormatQuery (commandText, commandType, parameters);
381 if ((behavior & CommandBehavior.KeyInfo) != 0)
382 sql += " FOR BROWSE";
387 #endregion // Methods