SqlCommandBuilder.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876
  1. //
  2. // System.Data.SqlClient.SqlCommandBuilder.cs
  3. //
  4. // Author:
  5. // Tim Coleman ([email protected])
  6. //
  7. // Copyright (C) Tim Coleman, 2002
  8. //
  9. //
  10. // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31. using System;
  32. using System.Collections;
  33. using System.ComponentModel;
  34. using System.Data;
  35. using System.Data.Common;
  36. #if NET_2_0
  37. using System.Data.SqlTypes;
  38. #endif
  39. using System.Text;
  40. namespace System.Data.SqlClient
  41. {
  42. #if NET_2_0
  43. public sealed class SqlCommandBuilder : DbCommandBuilder
  44. #else
  45. public sealed class SqlCommandBuilder : Component
  46. #endif // NET_2_0
  47. {
  48. #region Fields
  49. #if ONLY_1_1
  50. bool disposed;
  51. DataTable dbSchemaTable;
  52. string quotePrefix;
  53. string quoteSuffix;
  54. string tableName;
  55. SqlDataAdapter adapter;
  56. SqlCommand insertCommand;
  57. SqlCommand deleteCommand;
  58. SqlCommand updateCommand;
  59. // Used to construct WHERE clauses
  60. static readonly string clause1 = "({0} = 1 AND {1} IS NULL)";
  61. static readonly string clause2 = "({0} = {1})";
  62. #else
  63. readonly string _catalogSeparator = ".";
  64. readonly string _schemaSeparator = ".";
  65. readonly CatalogLocation _catalogLocation = CatalogLocation.Start;
  66. #endif
  67. #endregion // Fields
  68. #region Constructors
  69. public SqlCommandBuilder ()
  70. {
  71. #if NET_2_0
  72. QuoteSuffix = "]";
  73. QuotePrefix = "[";
  74. #endif
  75. }
  76. public SqlCommandBuilder (SqlDataAdapter adapter)
  77. : this ()
  78. {
  79. DataAdapter = adapter;
  80. }
  81. #endregion // Constructors
  82. #region Properties
  83. #if !NET_2_0
  84. [DataSysDescription ("The DataAdapter for which to automatically generate SqlCommands")]
  85. #endif
  86. [DefaultValue (null)]
  87. public new SqlDataAdapter DataAdapter {
  88. get {
  89. #if ONLY_1_1
  90. return adapter;
  91. #else
  92. return (SqlDataAdapter)base.DataAdapter;
  93. #endif
  94. } set {
  95. #if ONLY_1_1
  96. if (adapter != null)
  97. adapter.RowUpdating -= new SqlRowUpdatingEventHandler (RowUpdatingHandler);
  98. adapter = value;
  99. if (adapter != null)
  100. adapter.RowUpdating += new SqlRowUpdatingEventHandler (RowUpdatingHandler);
  101. #else
  102. base.DataAdapter = value;
  103. #endif
  104. }
  105. }
  106. [Browsable (false)]
  107. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  108. #if !NET_2_0
  109. [DataSysDescription ("The character used in a text command as the opening quote for quoting identifiers that contain special characters.")]
  110. #else
  111. [EditorBrowsable (EditorBrowsableState.Never)]
  112. #endif // NET_2_0
  113. public
  114. #if NET_2_0
  115. override
  116. #endif // NET_2_0
  117. string QuotePrefix {
  118. get {
  119. #if ONLY_1_1
  120. if (quotePrefix == null)
  121. return string.Empty;
  122. return quotePrefix;
  123. #else
  124. return base.QuotePrefix;
  125. #endif
  126. }
  127. set {
  128. #if ONLY_1_1
  129. if (dbSchemaTable != null)
  130. throw new InvalidOperationException (
  131. "The QuotePrefix and QuoteSuffix " +
  132. "properties cannot be changed once " +
  133. "an Insert, Update, or Delete " +
  134. "command has been generated.");
  135. quotePrefix = value;
  136. #else
  137. if (value != "[" && value != "\"")
  138. throw new ArgumentException ("Only '[' " +
  139. "and '\"' are allowed as value " +
  140. "for the 'QuoteSuffix' property.");
  141. base.QuotePrefix = value;
  142. #endif
  143. }
  144. }
  145. [Browsable (false)]
  146. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  147. #if !NET_2_0
  148. [DataSysDescription ("The character used in a text command as the closing quote for quoting identifiers that contain special characters. ")]
  149. #else
  150. [EditorBrowsable (EditorBrowsableState.Never)]
  151. #endif // NET_2_0
  152. public
  153. #if NET_2_0
  154. override
  155. #endif // NET_2_0
  156. string QuoteSuffix {
  157. get {
  158. #if ONLY_1_1
  159. if (quoteSuffix == null)
  160. return string.Empty;
  161. return quoteSuffix;
  162. #else
  163. return base.QuoteSuffix;
  164. #endif
  165. }
  166. set {
  167. #if ONLY_1_1
  168. if (dbSchemaTable != null)
  169. throw new InvalidOperationException (
  170. "The QuotePrefix and QuoteSuffix " +
  171. "properties cannot be changed once " +
  172. "an Insert, Update, or Delete " +
  173. "command has been generated.");
  174. quoteSuffix = value;
  175. #else
  176. if (value != "]" && value != "\"")
  177. throw new ArgumentException ("Only ']' " +
  178. "and '\"' are allowed as value " +
  179. "for the 'QuoteSuffix' property.");
  180. base.QuoteSuffix = value;
  181. #endif
  182. }
  183. }
  184. #if NET_2_0
  185. [EditorBrowsable (EditorBrowsableState.Never)]
  186. [Browsable (false)]
  187. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  188. #if !NET_2_0
  189. [DefaultValue (".")]
  190. #endif
  191. public override string CatalogSeparator {
  192. get { return _catalogSeparator; }
  193. set {
  194. if (value != _catalogSeparator)
  195. throw new ArgumentException ("Only " +
  196. "'.' is allowed as value " +
  197. "for the 'CatalogSeparator' " +
  198. "property.");
  199. }
  200. }
  201. [EditorBrowsable (EditorBrowsableState.Never)]
  202. [Browsable (false)]
  203. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  204. #if !NET_2_0
  205. [DefaultValue (".")]
  206. #endif
  207. public override string SchemaSeparator {
  208. get { return _schemaSeparator; }
  209. set {
  210. if (value != _schemaSeparator)
  211. throw new ArgumentException ("Only " +
  212. "'.' is allowed as value " +
  213. "for the 'SchemaSeparator' " +
  214. "property.");
  215. }
  216. }
  217. [EditorBrowsable (EditorBrowsableState.Never)]
  218. [Browsable (false)]
  219. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  220. #if !NET_2_0
  221. [DefaultValue (CatalogLocation.Start)]
  222. #endif
  223. public override CatalogLocation CatalogLocation {
  224. get { return _catalogLocation; }
  225. set {
  226. if (value != CatalogLocation.Start)
  227. throw new ArgumentException ("Only " +
  228. "'Start' is allowed as value " +
  229. "for the 'CatalogLocation' " +
  230. "property.");
  231. }
  232. }
  233. #endif // NET_2_0
  234. #if ONLY_1_1
  235. private SqlCommand SourceCommand {
  236. get {
  237. if (adapter != null)
  238. return adapter.SelectCommand;
  239. return null;
  240. }
  241. }
  242. #endif
  243. #endregion // Properties
  244. #region Methods
  245. #if ONLY_1_1
  246. private void BuildCache (bool closeConnection)
  247. {
  248. SqlCommand sourceCommand = SourceCommand;
  249. if (sourceCommand == null)
  250. throw new InvalidOperationException ("The DataAdapter.SelectCommand property needs to be initialized.");
  251. SqlConnection connection = sourceCommand.Connection;
  252. if (connection == null)
  253. throw new InvalidOperationException ("The DataAdapter.SelectCommand.Connection property needs to be initialized.");
  254. if (dbSchemaTable == null) {
  255. if (connection.State == ConnectionState.Open)
  256. closeConnection = false;
  257. else
  258. connection.Open ();
  259. SqlDataReader reader = sourceCommand.ExecuteReader (CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo);
  260. dbSchemaTable = reader.GetSchemaTable ();
  261. reader.Close ();
  262. if (closeConnection)
  263. connection.Close ();
  264. BuildInformation (dbSchemaTable);
  265. }
  266. }
  267. private void BuildInformation (DataTable schemaTable)
  268. {
  269. tableName = String.Empty;
  270. foreach (DataRow schemaRow in schemaTable.Rows) {
  271. if (schemaRow.IsNull ("BaseTableName") ||
  272. (string) schemaRow ["BaseTableName"] == String.Empty)
  273. continue;
  274. if (tableName == String.Empty)
  275. tableName = (string) schemaRow ["BaseTableName"];
  276. else if (tableName != (string) schemaRow["BaseTableName"])
  277. throw new InvalidOperationException ("Dynamic SQL generation is not supported against multiple base tables.");
  278. }
  279. if (tableName == String.Empty)
  280. throw new InvalidOperationException ("Dynamic SQL generation is not supported with no base table.");
  281. dbSchemaTable = schemaTable;
  282. }
  283. private SqlCommand CreateDeleteCommand (bool useColumnsForParameterNames)
  284. {
  285. // If no table was found, then we can't do an delete
  286. if (QuotedTableName == String.Empty)
  287. return null;
  288. CreateNewCommand (ref deleteCommand);
  289. string command = String.Format ("DELETE FROM {0}", QuotedTableName);
  290. StringBuilder whereClause = new StringBuilder ();
  291. bool keyFound = false;
  292. int parmIndex = 1;
  293. foreach (DataRow schemaRow in dbSchemaTable.Rows) {
  294. if ((bool)schemaRow["IsExpression"] == true)
  295. continue;
  296. if (!IncludedInWhereClause (schemaRow))
  297. continue;
  298. if (whereClause.Length > 0)
  299. whereClause.Append (" AND ");
  300. bool isKey = (bool) schemaRow ["IsKey"];
  301. SqlParameter parameter = null;
  302. if (isKey)
  303. keyFound = true;
  304. bool allowNull = (bool) schemaRow ["AllowDBNull"];
  305. if (!isKey) {
  306. string sourceColumnName = (string) schemaRow ["BaseColumnName"];
  307. if (useColumnsForParameterNames) {
  308. parameter = deleteCommand.Parameters.Add (
  309. GetNullCheckParameterName (sourceColumnName),
  310. SqlDbType.Int);
  311. } else {
  312. parameter = deleteCommand.Parameters.Add (
  313. GetParameterName (parmIndex++),
  314. SqlDbType.Int);
  315. }
  316. parameter.IsNullable = allowNull;
  317. parameter.SourceVersion = DataRowVersion.Current;
  318. parameter.Value = 1;
  319. whereClause.Append ("(");
  320. whereClause.Append (String.Format (clause1, parameter.ParameterName,
  321. GetQuotedString (sourceColumnName)));
  322. whereClause.Append (" OR ");
  323. }
  324. if (useColumnsForParameterNames)
  325. parameter = CreateParameter (schemaRow, true);
  326. else
  327. parameter = CreateParameter (parmIndex++, schemaRow);
  328. deleteCommand.Parameters.Add (parameter);
  329. ApplyParameterInfo (parameter, schemaRow, StatementType.Delete, true);
  330. parameter.IsNullable = allowNull;
  331. parameter.SourceVersion = DataRowVersion.Original;
  332. whereClause.Append (String.Format (clause2, GetQuotedString (parameter.SourceColumn), parameter.ParameterName));
  333. if (!isKey)
  334. whereClause.Append (")");
  335. }
  336. if (!keyFound)
  337. throw new InvalidOperationException ("Dynamic SQL generation for the DeleteCommand is not supported against a SelectCommand that does not return any key column information.");
  338. // We're all done, so bring it on home
  339. string sql = String.Format ("{0} WHERE ( {1} )", command, whereClause.ToString ());
  340. deleteCommand.CommandText = sql;
  341. return deleteCommand;
  342. }
  343. private SqlCommand CreateInsertCommand (bool useColumnsForParameterNames)
  344. {
  345. if (QuotedTableName == String.Empty)
  346. return null;
  347. CreateNewCommand (ref insertCommand);
  348. string command = String.Format ("INSERT INTO {0}", QuotedTableName);
  349. string sql;
  350. StringBuilder columns = new StringBuilder ();
  351. StringBuilder values = new StringBuilder ();
  352. int parmIndex = 1;
  353. foreach (DataRow schemaRow in dbSchemaTable.Rows) {
  354. if (!IncludedInInsert (schemaRow))
  355. continue;
  356. if (parmIndex > 1) {
  357. columns.Append (" , ");
  358. values.Append (" , ");
  359. }
  360. SqlParameter parameter = null;
  361. if (useColumnsForParameterNames) {
  362. parameter = CreateParameter (schemaRow, false);
  363. } else {
  364. parameter = CreateParameter (parmIndex, schemaRow);
  365. }
  366. insertCommand.Parameters.Add (parameter);
  367. ApplyParameterInfo (parameter, schemaRow, StatementType.Insert, false);
  368. parameter.SourceVersion = DataRowVersion.Current;
  369. parameter.IsNullable = (bool) schemaRow ["AllowDBNull"];
  370. columns.Append (GetQuotedString (parameter.SourceColumn));
  371. values.Append (parameter.ParameterName);
  372. parmIndex++;
  373. }
  374. sql = String.Format ("{0}( {1} ) VALUES ( {2} )", command, columns.ToString (), values.ToString ());
  375. insertCommand.CommandText = sql;
  376. return insertCommand;
  377. }
  378. private void CreateNewCommand (ref SqlCommand command)
  379. {
  380. SqlCommand sourceCommand = SourceCommand;
  381. if (command == null) {
  382. command = sourceCommand.Connection.CreateCommand ();
  383. command.CommandTimeout = sourceCommand.CommandTimeout;
  384. command.Transaction = sourceCommand.Transaction;
  385. }
  386. command.CommandType = CommandType.Text;
  387. command.UpdatedRowSource = UpdateRowSource.None;
  388. command.Parameters.Clear ();
  389. }
  390. private SqlCommand CreateUpdateCommand (bool useColumnsForParameterNames)
  391. {
  392. // If no table was found, then we can't do an update
  393. if (QuotedTableName == String.Empty)
  394. return null;
  395. CreateNewCommand (ref updateCommand);
  396. string command = String.Format ("UPDATE {0} SET ", QuotedTableName);
  397. StringBuilder columns = new StringBuilder ();
  398. StringBuilder whereClause = new StringBuilder ();
  399. int parmIndex = 1;
  400. bool keyFound = false;
  401. // First, create the X=Y list for UPDATE
  402. foreach (DataRow schemaRow in dbSchemaTable.Rows) {
  403. if (!IncludedInUpdate (schemaRow))
  404. continue;
  405. if (columns.Length > 0)
  406. columns.Append (" , ");
  407. SqlParameter parameter = null;
  408. if (useColumnsForParameterNames) {
  409. parameter = CreateParameter (schemaRow, false);
  410. } else {
  411. parameter = CreateParameter (parmIndex++, schemaRow);
  412. }
  413. updateCommand.Parameters.Add (parameter);
  414. ApplyParameterInfo (parameter, schemaRow, StatementType.Update, false);
  415. parameter.IsNullable = (bool) schemaRow ["AllowDBNull"];
  416. parameter.SourceVersion = DataRowVersion.Current;
  417. columns.Append (String.Format ("{0} = {1}", GetQuotedString (parameter.SourceColumn), parameter.ParameterName));
  418. }
  419. // Now, create the WHERE clause. This may be optimizable, but it would be ugly to incorporate
  420. // into the loop above. "Premature optimization is the root of all evil." -- Knuth
  421. foreach (DataRow schemaRow in dbSchemaTable.Rows) {
  422. if ((bool)schemaRow["IsExpression"] == true)
  423. continue;
  424. if (!IncludedInWhereClause (schemaRow))
  425. continue;
  426. if (whereClause.Length > 0)
  427. whereClause.Append (" AND ");
  428. bool isKey = (bool) schemaRow ["IsKey"];
  429. SqlParameter parameter = null;
  430. if (isKey)
  431. keyFound = true;
  432. bool allowNull = (bool) schemaRow ["AllowDBNull"];
  433. if (!isKey) {
  434. string sourceColumnName = (string) schemaRow ["BaseColumnName"];
  435. if (useColumnsForParameterNames) {
  436. parameter = updateCommand.Parameters.Add (
  437. GetNullCheckParameterName (sourceColumnName),
  438. SqlDbType.Int);
  439. } else {
  440. parameter = updateCommand.Parameters.Add (
  441. GetParameterName (parmIndex++),
  442. SqlDbType.Int);
  443. }
  444. parameter.IsNullable = allowNull;
  445. parameter.SourceVersion = DataRowVersion.Current;
  446. parameter.Value = 1;
  447. whereClause.Append ("(");
  448. whereClause.Append (String.Format (clause1, parameter.ParameterName,
  449. GetQuotedString (sourceColumnName)));
  450. whereClause.Append (" OR ");
  451. }
  452. if (useColumnsForParameterNames) {
  453. parameter = CreateParameter (schemaRow, true);
  454. } else {
  455. parameter = CreateParameter (parmIndex++, schemaRow);
  456. }
  457. updateCommand.Parameters.Add (parameter);
  458. ApplyParameterInfo (parameter, schemaRow, StatementType.Update, true);
  459. parameter.IsNullable = allowNull;
  460. parameter.SourceVersion = DataRowVersion.Original;
  461. whereClause.Append (String.Format (clause2, GetQuotedString (parameter.SourceColumn), parameter.ParameterName));
  462. if (!isKey)
  463. whereClause.Append (")");
  464. }
  465. if (!keyFound)
  466. throw new InvalidOperationException ("Dynamic SQL generation for the UpdateCommand is not supported against a SelectCommand that does not return any key column information.");
  467. // We're all done, so bring it on home
  468. string sql = String.Format ("{0}{1} WHERE ( {2} )", command, columns.ToString (), whereClause.ToString ());
  469. updateCommand.CommandText = sql;
  470. return updateCommand;
  471. }
  472. private SqlParameter CreateParameter (DataRow schemaRow, bool whereClause)
  473. {
  474. string sourceColumn = (string) schemaRow ["BaseColumnName"];
  475. string name;
  476. if (whereClause)
  477. name = GetParameterName ("Original_" + sourceColumn);
  478. else
  479. name = GetParameterName (sourceColumn);
  480. SqlParameter param = new SqlParameter ();
  481. param.ParameterName = name;
  482. param.SourceColumn = sourceColumn;
  483. return param;
  484. }
  485. private SqlParameter CreateParameter (int paramIndex, DataRow schemaRow)
  486. {
  487. string sourceColumn = (string) schemaRow ["BaseColumnName"];
  488. string name = GetParameterName (paramIndex);
  489. SqlParameter param = new SqlParameter ();
  490. param.ParameterName = name;
  491. param.SourceColumn = sourceColumn;
  492. return param;
  493. }
  494. #endif // ONLY_1_1
  495. public static void DeriveParameters (SqlCommand command)
  496. {
  497. command.DeriveParameters ();
  498. }
  499. #if ONLY_1_1
  500. protected override void Dispose (bool disposing)
  501. {
  502. if (!disposed) {
  503. if (disposing) {
  504. if (insertCommand != null)
  505. insertCommand.Dispose ();
  506. if (deleteCommand != null)
  507. deleteCommand.Dispose ();
  508. if (updateCommand != null)
  509. updateCommand.Dispose ();
  510. if (dbSchemaTable != null)
  511. dbSchemaTable.Dispose ();
  512. }
  513. disposed = true;
  514. }
  515. }
  516. #endif
  517. public
  518. #if NET_2_0
  519. new
  520. #endif // NET_2_0
  521. SqlCommand GetDeleteCommand ()
  522. {
  523. #if NET_2_0
  524. return (SqlCommand) base.GetDeleteCommand (false);
  525. #else
  526. BuildCache (true);
  527. if (deleteCommand == null)
  528. return CreateDeleteCommand (false);
  529. return deleteCommand;
  530. #endif
  531. }
  532. public
  533. #if NET_2_0
  534. new
  535. #endif // NET_2_0
  536. SqlCommand GetInsertCommand ()
  537. {
  538. #if NET_2_0
  539. return (SqlCommand) base.GetInsertCommand (false);
  540. #else
  541. BuildCache (true);
  542. if (insertCommand == null)
  543. return CreateInsertCommand (false);
  544. return insertCommand;
  545. #endif
  546. }
  547. public
  548. #if NET_2_0
  549. new
  550. #endif // NET_2_0
  551. SqlCommand GetUpdateCommand ()
  552. {
  553. #if NET_2_0
  554. return (SqlCommand) base.GetUpdateCommand (false);
  555. #else
  556. BuildCache (true);
  557. if (updateCommand == null)
  558. return CreateUpdateCommand (false);
  559. return updateCommand;
  560. #endif
  561. }
  562. #if NET_2_0
  563. public new SqlCommand GetUpdateCommand (bool useColumnsForParameterNames)
  564. {
  565. return (SqlCommand) base.GetUpdateCommand (useColumnsForParameterNames);
  566. }
  567. public new SqlCommand GetDeleteCommand (bool useColumnsForParameterNames)
  568. {
  569. return (SqlCommand) base.GetDeleteCommand (useColumnsForParameterNames);
  570. }
  571. public new SqlCommand GetInsertCommand (bool useColumnsForParameterNames)
  572. {
  573. return (SqlCommand) base.GetInsertCommand (useColumnsForParameterNames);
  574. }
  575. public override string QuoteIdentifier (string unquotedIdentifier)
  576. {
  577. if (unquotedIdentifier == null)
  578. throw new ArgumentNullException ("unquotedIdentifier");
  579. string prefix = QuotePrefix;
  580. string suffix = QuoteSuffix;
  581. if ((prefix == "[" && suffix != "]") || (prefix == "\"" && suffix != "\""))
  582. throw new ArgumentException ("The QuotePrefix " +
  583. "and QuoteSuffix properties do not match.");
  584. string escaped = unquotedIdentifier.Replace (suffix,
  585. suffix + suffix);
  586. return string.Concat (prefix, escaped, suffix);
  587. }
  588. public override string UnquoteIdentifier (string quotedIdentifier)
  589. {
  590. return base.UnquoteIdentifier (quotedIdentifier);
  591. }
  592. #endif // NET_2_0
  593. private bool IncludedInInsert (DataRow schemaRow)
  594. {
  595. // If the parameter has one of these properties, then we don't include it in the insert:
  596. // AutoIncrement, Hidden, Expression, RowVersion, ReadOnly
  597. if (!schemaRow.IsNull ("IsAutoIncrement") && (bool) schemaRow ["IsAutoIncrement"])
  598. return false;
  599. if (!schemaRow.IsNull ("IsHidden") && (bool) schemaRow ["IsHidden"])
  600. return false;
  601. if (!schemaRow.IsNull ("IsExpression") && (bool) schemaRow ["IsExpression"])
  602. return false;
  603. if (!schemaRow.IsNull ("IsRowVersion") && (bool) schemaRow ["IsRowVersion"])
  604. return false;
  605. if (!schemaRow.IsNull ("IsReadOnly") && (bool) schemaRow ["IsReadOnly"])
  606. return false;
  607. return true;
  608. }
  609. private bool IncludedInUpdate (DataRow schemaRow)
  610. {
  611. // If the parameter has one of these properties, then we don't include it in the insert:
  612. // AutoIncrement, Hidden, RowVersion
  613. if (!schemaRow.IsNull ("IsAutoIncrement") && (bool) schemaRow ["IsAutoIncrement"])
  614. return false;
  615. if (!schemaRow.IsNull ("IsHidden") && (bool) schemaRow ["IsHidden"])
  616. return false;
  617. if (!schemaRow.IsNull ("IsRowVersion") && (bool) schemaRow ["IsRowVersion"])
  618. return false;
  619. if (!schemaRow.IsNull ("IsExpression") && (bool) schemaRow ["IsExpression"])
  620. return false;
  621. if (!schemaRow.IsNull ("IsReadOnly") && (bool) schemaRow ["IsReadOnly"])
  622. return false;
  623. return true;
  624. }
  625. private bool IncludedInWhereClause (DataRow schemaRow)
  626. {
  627. if ((bool) schemaRow ["IsLong"])
  628. return false;
  629. return true;
  630. }
  631. #if ONLY_1_1
  632. private string GetQuotedString (string value)
  633. {
  634. if (value == null || value.Length == 0)
  635. return value;
  636. string prefix = QuotePrefix;
  637. string suffix = QuoteSuffix;
  638. if (prefix.Length == 0 && suffix.Length == 0)
  639. return value;
  640. return String.Format ("{0}{1}{2}", prefix, value, suffix);
  641. }
  642. string GetNullCheckParameterName (string parameterName)
  643. {
  644. return GetParameterName ("IsNull_" + parameterName);
  645. }
  646. private string QuotedTableName {
  647. get { return GetQuotedString (tableName); }
  648. }
  649. public void RefreshSchema ()
  650. {
  651. // FIXME: "Figure out what else needs to be cleaned up when we refresh."
  652. tableName = String.Empty;
  653. dbSchemaTable = null;
  654. deleteCommand = null;
  655. insertCommand = null;
  656. updateCommand = null;
  657. }
  658. #endif
  659. #if NET_2_0
  660. protected override void ApplyParameterInfo (DbParameter parameter,
  661. DataRow datarow,
  662. StatementType statementType,
  663. bool whereClause)
  664. {
  665. SqlParameter sqlParam = (SqlParameter) parameter;
  666. #else
  667. void ApplyParameterInfo (SqlParameter sqlParam,
  668. DataRow datarow,
  669. StatementType statementType,
  670. bool whereClause)
  671. {
  672. #endif
  673. sqlParam.SqlDbType = (SqlDbType) datarow ["ProviderType"];
  674. object precision = datarow ["NumericPrecision"];
  675. if (precision != DBNull.Value) {
  676. short val = (short) precision;
  677. if (val < byte.MaxValue && val >= byte.MinValue)
  678. sqlParam.Precision = (byte) val;
  679. }
  680. object scale = datarow ["NumericScale"];
  681. if (scale != DBNull.Value) {
  682. short val = ((short) scale);
  683. if (val < byte.MaxValue && val >= byte.MinValue)
  684. sqlParam.Scale = (byte) val;
  685. }
  686. }
  687. #if NET_2_0
  688. protected override
  689. #endif
  690. string GetParameterName (int parameterOrdinal)
  691. {
  692. return String.Format ("@p{0}", parameterOrdinal);
  693. }
  694. #if NET_2_0
  695. protected override
  696. #endif
  697. string GetParameterName (string parameterName)
  698. {
  699. return String.Format ("@{0}", parameterName);
  700. }
  701. #if NET_2_0
  702. protected override string GetParameterPlaceholder (int parameterOrdinal)
  703. {
  704. return GetParameterName (parameterOrdinal);
  705. }
  706. #endif
  707. #endregion // Methods
  708. #region Event Handlers
  709. void RowUpdatingHandler (object sender, SqlRowUpdatingEventArgs args)
  710. {
  711. if (args.Command != null)
  712. return;
  713. try {
  714. switch (args.StatementType) {
  715. case StatementType.Insert:
  716. args.Command = GetInsertCommand ();
  717. break;
  718. case StatementType.Update:
  719. args.Command = GetUpdateCommand ();
  720. break;
  721. case StatementType.Delete:
  722. args.Command = GetDeleteCommand ();
  723. break;
  724. }
  725. } catch (Exception e) {
  726. args.Errors = e;
  727. args.Status = UpdateStatus.ErrorsOccurred;
  728. }
  729. }
  730. #if NET_2_0
  731. protected override void SetRowUpdatingHandler (DbDataAdapter adapter)
  732. {
  733. SqlDataAdapter sda = adapter as SqlDataAdapter;
  734. if (sda == null) {
  735. throw new InvalidOperationException ("Adapter needs to be a SqlDataAdapter");
  736. }
  737. if (sda != base.DataAdapter)
  738. sda.RowUpdating += new SqlRowUpdatingEventHandler (RowUpdatingHandler);
  739. else
  740. sda.RowUpdating -= new SqlRowUpdatingEventHandler (RowUpdatingHandler);;
  741. }
  742. protected override DataTable GetSchemaTable (DbCommand srcCommand)
  743. {
  744. using (SqlDataReader rdr = (SqlDataReader) srcCommand.ExecuteReader (CommandBehavior.KeyInfo | CommandBehavior.SchemaOnly))
  745. return rdr.GetSchemaTable ();
  746. }
  747. protected override DbCommand InitializeCommand (DbCommand command)
  748. {
  749. if (command == null) {
  750. command = new SqlCommand ();
  751. } else {
  752. command.CommandTimeout = 30;
  753. command.Transaction = null;
  754. command.CommandType = CommandType.Text;
  755. command.UpdatedRowSource = UpdateRowSource.None;
  756. }
  757. return command;
  758. }
  759. #endif // NET_2_0
  760. #endregion // Event Handlers
  761. }
  762. }