882 lines
25 KiB
C#
882 lines
25 KiB
C#
|
//
|
||
|
// System.Data.SqlClient.SqlCommandBuilder.cs
|
||
|
//
|
||
|
// Author:
|
||
|
// Tim Coleman (tim@timcoleman.com)
|
||
|
// Veerapuram Varadhan (vvaradhan@novell.com)
|
||
|
//
|
||
|
// Copyright (C) Tim Coleman, 2002
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Copyright (C) 2004, 2009 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.
|
||
|
//
|
||
|
|
||
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.ComponentModel;
|
||
|
using System.Data;
|
||
|
using System.Data.Common;
|
||
|
#if NET_2_0
|
||
|
using System.Data.SqlTypes;
|
||
|
#endif
|
||
|
using System.Text;
|
||
|
|
||
|
namespace System.Data.SqlClient
|
||
|
{
|
||
|
#if NET_2_0
|
||
|
public sealed class SqlCommandBuilder : DbCommandBuilder
|
||
|
#else
|
||
|
public sealed class SqlCommandBuilder : Component
|
||
|
#endif // NET_2_0
|
||
|
{
|
||
|
#region Fields
|
||
|
|
||
|
#if ONLY_1_1
|
||
|
bool disposed;
|
||
|
|
||
|
DataTable dbSchemaTable;
|
||
|
string quotePrefix;
|
||
|
string quoteSuffix;
|
||
|
string tableName;
|
||
|
SqlDataAdapter adapter;
|
||
|
SqlCommand insertCommand;
|
||
|
SqlCommand deleteCommand;
|
||
|
SqlCommand updateCommand;
|
||
|
// Used to construct WHERE clauses
|
||
|
static readonly string clause1 = "({0} = 1 AND {1} IS NULL)";
|
||
|
static readonly string clause2 = "({0} = {1})";
|
||
|
|
||
|
#else
|
||
|
readonly string _catalogSeparator = ".";
|
||
|
readonly string _schemaSeparator = ".";
|
||
|
readonly CatalogLocation _catalogLocation = CatalogLocation.Start;
|
||
|
#endif
|
||
|
|
||
|
#endregion // Fields
|
||
|
|
||
|
#region Constructors
|
||
|
|
||
|
public SqlCommandBuilder ()
|
||
|
{
|
||
|
#if NET_2_0
|
||
|
QuoteSuffix = "]";
|
||
|
QuotePrefix = "[";
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
public SqlCommandBuilder (SqlDataAdapter adapter)
|
||
|
: this ()
|
||
|
{
|
||
|
DataAdapter = adapter;
|
||
|
}
|
||
|
|
||
|
#endregion // Constructors
|
||
|
|
||
|
#region Properties
|
||
|
|
||
|
#if !NET_2_0
|
||
|
[DataSysDescription ("The DataAdapter for which to automatically generate SqlCommands")]
|
||
|
#endif
|
||
|
[DefaultValue (null)]
|
||
|
public new SqlDataAdapter DataAdapter {
|
||
|
get {
|
||
|
#if ONLY_1_1
|
||
|
return adapter;
|
||
|
#else
|
||
|
return (SqlDataAdapter)base.DataAdapter;
|
||
|
#endif
|
||
|
} set {
|
||
|
#if ONLY_1_1
|
||
|
if (adapter != null)
|
||
|
adapter.RowUpdating -= new SqlRowUpdatingEventHandler (RowUpdatingHandler);
|
||
|
|
||
|
adapter = value;
|
||
|
if (adapter != null)
|
||
|
adapter.RowUpdating += new SqlRowUpdatingEventHandler (RowUpdatingHandler);
|
||
|
#else
|
||
|
base.DataAdapter = value;
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Browsable (false)]
|
||
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
||
|
#if !NET_2_0
|
||
|
[DataSysDescription ("The character used in a text command as the opening quote for quoting identifiers that contain special characters.")]
|
||
|
#else
|
||
|
[EditorBrowsable (EditorBrowsableState.Never)]
|
||
|
#endif // NET_2_0
|
||
|
public
|
||
|
#if NET_2_0
|
||
|
override
|
||
|
#endif // NET_2_0
|
||
|
string QuotePrefix {
|
||
|
get {
|
||
|
#if ONLY_1_1
|
||
|
if (quotePrefix == null)
|
||
|
return string.Empty;
|
||
|
return quotePrefix;
|
||
|
#else
|
||
|
return base.QuotePrefix;
|
||
|
#endif
|
||
|
}
|
||
|
set {
|
||
|
#if ONLY_1_1
|
||
|
if (dbSchemaTable != null)
|
||
|
throw new InvalidOperationException (
|
||
|
"The QuotePrefix and QuoteSuffix " +
|
||
|
"properties cannot be changed once " +
|
||
|
"an Insert, Update, or Delete " +
|
||
|
"command has been generated.");
|
||
|
quotePrefix = value;
|
||
|
#else
|
||
|
if (value != "[" && value != "\"")
|
||
|
throw new ArgumentException ("Only '[' " +
|
||
|
"and '\"' are allowed as value " +
|
||
|
"for the 'QuoteSuffix' property.");
|
||
|
base.QuotePrefix = value;
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Browsable (false)]
|
||
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
||
|
#if !NET_2_0
|
||
|
[DataSysDescription ("The character used in a text command as the closing quote for quoting identifiers that contain special characters. ")]
|
||
|
#else
|
||
|
[EditorBrowsable (EditorBrowsableState.Never)]
|
||
|
#endif // NET_2_0
|
||
|
public
|
||
|
#if NET_2_0
|
||
|
override
|
||
|
#endif // NET_2_0
|
||
|
string QuoteSuffix {
|
||
|
get {
|
||
|
#if ONLY_1_1
|
||
|
if (quoteSuffix == null)
|
||
|
return string.Empty;
|
||
|
return quoteSuffix;
|
||
|
#else
|
||
|
return base.QuoteSuffix;
|
||
|
#endif
|
||
|
}
|
||
|
set {
|
||
|
#if ONLY_1_1
|
||
|
if (dbSchemaTable != null)
|
||
|
throw new InvalidOperationException (
|
||
|
"The QuotePrefix and QuoteSuffix " +
|
||
|
"properties cannot be changed once " +
|
||
|
"an Insert, Update, or Delete " +
|
||
|
"command has been generated.");
|
||
|
quoteSuffix = value;
|
||
|
#else
|
||
|
if (value != "]" && value != "\"")
|
||
|
throw new ArgumentException ("Only ']' " +
|
||
|
"and '\"' are allowed as value " +
|
||
|
"for the 'QuoteSuffix' property.");
|
||
|
base.QuoteSuffix = value;
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if NET_2_0
|
||
|
[EditorBrowsable (EditorBrowsableState.Never)]
|
||
|
[Browsable (false)]
|
||
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
||
|
#if !NET_2_0
|
||
|
[DefaultValue (".")]
|
||
|
#endif
|
||
|
public override string CatalogSeparator {
|
||
|
get { return _catalogSeparator; }
|
||
|
set {
|
||
|
if (value != _catalogSeparator)
|
||
|
throw new ArgumentException ("Only " +
|
||
|
"'.' is allowed as value " +
|
||
|
"for the 'CatalogSeparator' " +
|
||
|
"property.");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[EditorBrowsable (EditorBrowsableState.Never)]
|
||
|
[Browsable (false)]
|
||
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
||
|
#if !NET_2_0
|
||
|
[DefaultValue (".")]
|
||
|
#endif
|
||
|
public override string SchemaSeparator {
|
||
|
get { return _schemaSeparator; }
|
||
|
set {
|
||
|
if (value != _schemaSeparator)
|
||
|
throw new ArgumentException ("Only " +
|
||
|
"'.' is allowed as value " +
|
||
|
"for the 'SchemaSeparator' " +
|
||
|
"property.");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[EditorBrowsable (EditorBrowsableState.Never)]
|
||
|
[Browsable (false)]
|
||
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
||
|
#if !NET_2_0
|
||
|
[DefaultValue (CatalogLocation.Start)]
|
||
|
#endif
|
||
|
public override CatalogLocation CatalogLocation {
|
||
|
get { return _catalogLocation; }
|
||
|
set {
|
||
|
if (value != CatalogLocation.Start)
|
||
|
throw new ArgumentException ("Only " +
|
||
|
"'Start' is allowed as value " +
|
||
|
"for the 'CatalogLocation' " +
|
||
|
"property.");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif // NET_2_0
|
||
|
|
||
|
#if ONLY_1_1
|
||
|
private SqlCommand SourceCommand {
|
||
|
get {
|
||
|
if (adapter != null)
|
||
|
return adapter.SelectCommand;
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#endregion // Properties
|
||
|
|
||
|
#region Methods
|
||
|
|
||
|
#if ONLY_1_1
|
||
|
private void BuildCache (bool closeConnection)
|
||
|
{
|
||
|
SqlCommand sourceCommand = SourceCommand;
|
||
|
if (sourceCommand == null)
|
||
|
throw new InvalidOperationException ("The DataAdapter.SelectCommand property needs to be initialized.");
|
||
|
SqlConnection connection = sourceCommand.Connection;
|
||
|
if (connection == null)
|
||
|
throw new InvalidOperationException ("The DataAdapter.SelectCommand.Connection property needs to be initialized.");
|
||
|
|
||
|
if (dbSchemaTable == null) {
|
||
|
if (connection.State == ConnectionState.Open)
|
||
|
closeConnection = false;
|
||
|
else
|
||
|
connection.Open ();
|
||
|
|
||
|
SqlDataReader reader = sourceCommand.ExecuteReader (CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo);
|
||
|
dbSchemaTable = reader.GetSchemaTable ();
|
||
|
reader.Close ();
|
||
|
if (closeConnection)
|
||
|
connection.Close ();
|
||
|
BuildInformation (dbSchemaTable);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void BuildInformation (DataTable schemaTable)
|
||
|
{
|
||
|
tableName = String.Empty;
|
||
|
foreach (DataRow schemaRow in schemaTable.Rows) {
|
||
|
if (schemaRow.IsNull ("BaseTableName") ||
|
||
|
(string) schemaRow ["BaseTableName"] == String.Empty)
|
||
|
continue;
|
||
|
|
||
|
if (tableName == String.Empty)
|
||
|
tableName = (string) schemaRow ["BaseTableName"];
|
||
|
else if (tableName != (string) schemaRow["BaseTableName"])
|
||
|
throw new InvalidOperationException ("Dynamic SQL generation is not supported against multiple base tables.");
|
||
|
}
|
||
|
if (tableName == String.Empty)
|
||
|
throw new InvalidOperationException ("Dynamic SQL generation is not supported with no base table.");
|
||
|
dbSchemaTable = schemaTable;
|
||
|
}
|
||
|
|
||
|
private SqlCommand CreateDeleteCommand (bool useColumnsForParameterNames)
|
||
|
{
|
||
|
// If no table was found, then we can't do an delete
|
||
|
if (QuotedTableName == String.Empty)
|
||
|
return null;
|
||
|
|
||
|
CreateNewCommand (ref deleteCommand);
|
||
|
|
||
|
string command = String.Format ("DELETE FROM {0}", QuotedTableName);
|
||
|
StringBuilder whereClause = new StringBuilder ();
|
||
|
bool keyFound = false;
|
||
|
int parmIndex = 1;
|
||
|
|
||
|
foreach (DataRow schemaRow in dbSchemaTable.Rows) {
|
||
|
if ((bool)schemaRow["IsExpression"] == true)
|
||
|
continue;
|
||
|
if (!IncludedInWhereClause (schemaRow))
|
||
|
continue;
|
||
|
|
||
|
if (whereClause.Length > 0)
|
||
|
whereClause.Append (" AND ");
|
||
|
|
||
|
bool isKey = (bool) schemaRow ["IsKey"];
|
||
|
SqlParameter parameter = null;
|
||
|
|
||
|
if (isKey)
|
||
|
keyFound = true;
|
||
|
|
||
|
bool allowNull = (bool) schemaRow ["AllowDBNull"];
|
||
|
if (!isKey) {
|
||
|
string sourceColumnName = (string) schemaRow ["BaseColumnName"];
|
||
|
if (useColumnsForParameterNames) {
|
||
|
parameter = deleteCommand.Parameters.Add (
|
||
|
GetNullCheckParameterName (sourceColumnName),
|
||
|
SqlDbType.Int);
|
||
|
} else {
|
||
|
parameter = deleteCommand.Parameters.Add (
|
||
|
GetParameterName (parmIndex++),
|
||
|
SqlDbType.Int);
|
||
|
}
|
||
|
parameter.IsNullable = allowNull;
|
||
|
parameter.SourceVersion = DataRowVersion.Current;
|
||
|
parameter.Value = 1;
|
||
|
|
||
|
whereClause.Append ("(");
|
||
|
whereClause.Append (String.Format (clause1, parameter.ParameterName,
|
||
|
GetQuotedString (sourceColumnName)));
|
||
|
whereClause.Append (" OR ");
|
||
|
}
|
||
|
|
||
|
if (useColumnsForParameterNames)
|
||
|
parameter = CreateParameter (schemaRow, true);
|
||
|
else
|
||
|
parameter = CreateParameter (parmIndex++, schemaRow);
|
||
|
deleteCommand.Parameters.Add (parameter);
|
||
|
ApplyParameterInfo (parameter, schemaRow, StatementType.Delete, true);
|
||
|
parameter.IsNullable = allowNull;
|
||
|
parameter.SourceVersion = DataRowVersion.Original;
|
||
|
|
||
|
whereClause.Append (String.Format (clause2, GetQuotedString (parameter.SourceColumn), parameter.ParameterName));
|
||
|
|
||
|
if (!isKey)
|
||
|
whereClause.Append (")");
|
||
|
}
|
||
|
if (!keyFound)
|
||
|
throw new InvalidOperationException ("Dynamic SQL generation for the DeleteCommand is not supported against a SelectCommand that does not return any key column information.");
|
||
|
|
||
|
// We're all done, so bring it on home
|
||
|
string sql = String.Format ("{0} WHERE ( {1} )", command, whereClause.ToString ());
|
||
|
deleteCommand.CommandText = sql;
|
||
|
return deleteCommand;
|
||
|
}
|
||
|
|
||
|
private SqlCommand CreateInsertCommand (bool useColumnsForParameterNames)
|
||
|
{
|
||
|
if (QuotedTableName == String.Empty)
|
||
|
return null;
|
||
|
|
||
|
CreateNewCommand (ref insertCommand);
|
||
|
|
||
|
string command = String.Format ("INSERT INTO {0}", QuotedTableName);
|
||
|
string sql;
|
||
|
StringBuilder columns = new StringBuilder ();
|
||
|
StringBuilder values = new StringBuilder ();
|
||
|
|
||
|
int parmIndex = 1;
|
||
|
foreach (DataRow schemaRow in dbSchemaTable.Rows) {
|
||
|
if (!IncludedInInsert (schemaRow))
|
||
|
continue;
|
||
|
|
||
|
if (parmIndex > 1) {
|
||
|
columns.Append (" , ");
|
||
|
values.Append (" , ");
|
||
|
}
|
||
|
|
||
|
SqlParameter parameter = null;
|
||
|
if (useColumnsForParameterNames) {
|
||
|
parameter = CreateParameter (schemaRow, false);
|
||
|
} else {
|
||
|
parameter = CreateParameter (parmIndex, schemaRow);
|
||
|
}
|
||
|
|
||
|
insertCommand.Parameters.Add (parameter);
|
||
|
ApplyParameterInfo (parameter, schemaRow, StatementType.Insert, false);
|
||
|
parameter.SourceVersion = DataRowVersion.Current;
|
||
|
parameter.IsNullable = (bool) schemaRow ["AllowDBNull"];
|
||
|
|
||
|
columns.Append (GetQuotedString (parameter.SourceColumn));
|
||
|
values.Append (parameter.ParameterName);
|
||
|
|
||
|
parmIndex++;
|
||
|
}
|
||
|
|
||
|
sql = String.Format ("{0}( {1} ) VALUES ( {2} )", command, columns.ToString (), values.ToString ());
|
||
|
insertCommand.CommandText = sql;
|
||
|
return insertCommand;
|
||
|
}
|
||
|
|
||
|
private void CreateNewCommand (ref SqlCommand command)
|
||
|
{
|
||
|
SqlCommand sourceCommand = SourceCommand;
|
||
|
if (command == null) {
|
||
|
command = sourceCommand.Connection.CreateCommand ();
|
||
|
command.CommandTimeout = sourceCommand.CommandTimeout;
|
||
|
command.Transaction = sourceCommand.Transaction;
|
||
|
}
|
||
|
command.CommandType = CommandType.Text;
|
||
|
command.UpdatedRowSource = UpdateRowSource.None;
|
||
|
command.Parameters.Clear ();
|
||
|
}
|
||
|
|
||
|
private SqlCommand CreateUpdateCommand (bool useColumnsForParameterNames)
|
||
|
{
|
||
|
// If no table was found, then we can't do an update
|
||
|
if (QuotedTableName == String.Empty)
|
||
|
return null;
|
||
|
|
||
|
CreateNewCommand (ref updateCommand);
|
||
|
|
||
|
string command = String.Format ("UPDATE {0} SET ", QuotedTableName);
|
||
|
StringBuilder columns = new StringBuilder ();
|
||
|
StringBuilder whereClause = new StringBuilder ();
|
||
|
int parmIndex = 1;
|
||
|
bool keyFound = false;
|
||
|
|
||
|
// First, create the X=Y list for UPDATE
|
||
|
foreach (DataRow schemaRow in dbSchemaTable.Rows) {
|
||
|
if (!IncludedInUpdate (schemaRow))
|
||
|
continue;
|
||
|
if (columns.Length > 0)
|
||
|
columns.Append (" , ");
|
||
|
|
||
|
SqlParameter parameter = null;
|
||
|
if (useColumnsForParameterNames) {
|
||
|
parameter = CreateParameter (schemaRow, false);
|
||
|
} else {
|
||
|
parameter = CreateParameter (parmIndex++, schemaRow);
|
||
|
}
|
||
|
updateCommand.Parameters.Add (parameter);
|
||
|
ApplyParameterInfo (parameter, schemaRow, StatementType.Update, false);
|
||
|
parameter.IsNullable = (bool) schemaRow ["AllowDBNull"];
|
||
|
parameter.SourceVersion = DataRowVersion.Current;
|
||
|
|
||
|
columns.Append (String.Format ("{0} = {1}", GetQuotedString (parameter.SourceColumn), parameter.ParameterName));
|
||
|
}
|
||
|
|
||
|
// Now, create the WHERE clause. This may be optimizable, but it would be ugly to incorporate
|
||
|
// into the loop above. "Premature optimization is the root of all evil." -- Knuth
|
||
|
foreach (DataRow schemaRow in dbSchemaTable.Rows) {
|
||
|
if ((bool)schemaRow["IsExpression"] == true)
|
||
|
continue;
|
||
|
|
||
|
if (!IncludedInWhereClause (schemaRow))
|
||
|
continue;
|
||
|
|
||
|
if (whereClause.Length > 0)
|
||
|
whereClause.Append (" AND ");
|
||
|
|
||
|
bool isKey = (bool) schemaRow ["IsKey"];
|
||
|
SqlParameter parameter = null;
|
||
|
|
||
|
if (isKey)
|
||
|
keyFound = true;
|
||
|
|
||
|
bool allowNull = (bool) schemaRow ["AllowDBNull"];
|
||
|
if (!isKey) {
|
||
|
string sourceColumnName = (string) schemaRow ["BaseColumnName"];
|
||
|
if (useColumnsForParameterNames) {
|
||
|
parameter = updateCommand.Parameters.Add (
|
||
|
GetNullCheckParameterName (sourceColumnName),
|
||
|
SqlDbType.Int);
|
||
|
} else {
|
||
|
parameter = updateCommand.Parameters.Add (
|
||
|
GetParameterName (parmIndex++),
|
||
|
SqlDbType.Int);
|
||
|
}
|
||
|
parameter.IsNullable = allowNull;
|
||
|
parameter.SourceVersion = DataRowVersion.Current;
|
||
|
parameter.Value = 1;
|
||
|
|
||
|
whereClause.Append ("(");
|
||
|
whereClause.Append (String.Format (clause1, parameter.ParameterName,
|
||
|
GetQuotedString (sourceColumnName)));
|
||
|
whereClause.Append (" OR ");
|
||
|
|
||
|
}
|
||
|
|
||
|
if (useColumnsForParameterNames) {
|
||
|
parameter = CreateParameter (schemaRow, true);
|
||
|
} else {
|
||
|
parameter = CreateParameter (parmIndex++, schemaRow);
|
||
|
}
|
||
|
updateCommand.Parameters.Add (parameter);
|
||
|
ApplyParameterInfo (parameter, schemaRow, StatementType.Update, true);
|
||
|
parameter.IsNullable = allowNull;
|
||
|
parameter.SourceVersion = DataRowVersion.Original;
|
||
|
|
||
|
whereClause.Append (String.Format (clause2, GetQuotedString (parameter.SourceColumn), parameter.ParameterName));
|
||
|
|
||
|
if (!isKey)
|
||
|
whereClause.Append (")");
|
||
|
}
|
||
|
if (!keyFound)
|
||
|
throw new InvalidOperationException ("Dynamic SQL generation for the UpdateCommand is not supported against a SelectCommand that does not return any key column information.");
|
||
|
|
||
|
// We're all done, so bring it on home
|
||
|
string sql = String.Format ("{0}{1} WHERE ( {2} )", command, columns.ToString (), whereClause.ToString ());
|
||
|
updateCommand.CommandText = sql;
|
||
|
return updateCommand;
|
||
|
}
|
||
|
|
||
|
private SqlParameter CreateParameter (DataRow schemaRow, bool whereClause)
|
||
|
{
|
||
|
string sourceColumn = (string) schemaRow ["BaseColumnName"];
|
||
|
string name;
|
||
|
if (whereClause)
|
||
|
name = GetParameterName ("Original_" + sourceColumn);
|
||
|
else
|
||
|
name = GetParameterName (sourceColumn);
|
||
|
|
||
|
SqlParameter param = new SqlParameter ();
|
||
|
param.ParameterName = name;
|
||
|
param.SourceColumn = sourceColumn;
|
||
|
return param;
|
||
|
}
|
||
|
|
||
|
private SqlParameter CreateParameter (int paramIndex, DataRow schemaRow)
|
||
|
{
|
||
|
string sourceColumn = (string) schemaRow ["BaseColumnName"];
|
||
|
string name = GetParameterName (paramIndex);
|
||
|
|
||
|
SqlParameter param = new SqlParameter ();
|
||
|
param.ParameterName = name;
|
||
|
param.SourceColumn = sourceColumn;
|
||
|
return param;
|
||
|
}
|
||
|
#endif // ONLY_1_1
|
||
|
|
||
|
public static void DeriveParameters (SqlCommand command)
|
||
|
{
|
||
|
command.DeriveParameters ();
|
||
|
}
|
||
|
|
||
|
#if ONLY_1_1
|
||
|
protected override void Dispose (bool disposing)
|
||
|
{
|
||
|
if (!disposed) {
|
||
|
if (disposing) {
|
||
|
if (insertCommand != null)
|
||
|
insertCommand.Dispose ();
|
||
|
if (deleteCommand != null)
|
||
|
deleteCommand.Dispose ();
|
||
|
if (updateCommand != null)
|
||
|
updateCommand.Dispose ();
|
||
|
if (dbSchemaTable != null)
|
||
|
dbSchemaTable.Dispose ();
|
||
|
}
|
||
|
disposed = true;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
public
|
||
|
#if NET_2_0
|
||
|
new
|
||
|
#endif // NET_2_0
|
||
|
SqlCommand GetDeleteCommand ()
|
||
|
{
|
||
|
#if NET_2_0
|
||
|
return (SqlCommand) base.GetDeleteCommand (false);
|
||
|
#else
|
||
|
BuildCache (true);
|
||
|
if (deleteCommand == null)
|
||
|
return CreateDeleteCommand (false);
|
||
|
return deleteCommand;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
public
|
||
|
#if NET_2_0
|
||
|
new
|
||
|
#endif // NET_2_0
|
||
|
SqlCommand GetInsertCommand ()
|
||
|
{
|
||
|
#if NET_2_0
|
||
|
return (SqlCommand) base.GetInsertCommand (false);
|
||
|
#else
|
||
|
BuildCache (true);
|
||
|
if (insertCommand == null)
|
||
|
return CreateInsertCommand (false);
|
||
|
return insertCommand;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
public
|
||
|
#if NET_2_0
|
||
|
new
|
||
|
#endif // NET_2_0
|
||
|
SqlCommand GetUpdateCommand ()
|
||
|
{
|
||
|
#if NET_2_0
|
||
|
return (SqlCommand) base.GetUpdateCommand (false);
|
||
|
#else
|
||
|
BuildCache (true);
|
||
|
if (updateCommand == null)
|
||
|
return CreateUpdateCommand (false);
|
||
|
return updateCommand;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#if NET_2_0
|
||
|
public new SqlCommand GetUpdateCommand (bool useColumnsForParameterNames)
|
||
|
{
|
||
|
return (SqlCommand) base.GetUpdateCommand (useColumnsForParameterNames);
|
||
|
}
|
||
|
|
||
|
public new SqlCommand GetDeleteCommand (bool useColumnsForParameterNames)
|
||
|
{
|
||
|
return (SqlCommand) base.GetDeleteCommand (useColumnsForParameterNames);
|
||
|
}
|
||
|
|
||
|
public new SqlCommand GetInsertCommand (bool useColumnsForParameterNames)
|
||
|
{
|
||
|
return (SqlCommand) base.GetInsertCommand (useColumnsForParameterNames);
|
||
|
}
|
||
|
|
||
|
public override string QuoteIdentifier (string unquotedIdentifier)
|
||
|
{
|
||
|
if (unquotedIdentifier == null)
|
||
|
throw new ArgumentNullException ("unquotedIdentifier");
|
||
|
|
||
|
string prefix = QuotePrefix;
|
||
|
string suffix = QuoteSuffix;
|
||
|
|
||
|
if ((prefix == "[" && suffix != "]") || (prefix == "\"" && suffix != "\""))
|
||
|
throw new ArgumentException ("The QuotePrefix " +
|
||
|
"and QuoteSuffix properties do not match.");
|
||
|
|
||
|
string escaped = unquotedIdentifier.Replace (suffix,
|
||
|
suffix + suffix);
|
||
|
return string.Concat (prefix, escaped, suffix);
|
||
|
}
|
||
|
|
||
|
public override string UnquoteIdentifier (string quotedIdentifier)
|
||
|
{
|
||
|
return base.UnquoteIdentifier (quotedIdentifier);
|
||
|
}
|
||
|
#endif // NET_2_0
|
||
|
|
||
|
private bool IncludedInInsert (DataRow schemaRow)
|
||
|
{
|
||
|
// If the parameter has one of these properties, then we don't include it in the insert:
|
||
|
// AutoIncrement, Hidden, Expression, RowVersion, ReadOnly
|
||
|
|
||
|
if (!schemaRow.IsNull ("IsAutoIncrement") && (bool) schemaRow ["IsAutoIncrement"])
|
||
|
return false;
|
||
|
if (!schemaRow.IsNull ("IsHidden") && (bool) schemaRow ["IsHidden"])
|
||
|
return false;
|
||
|
if (!schemaRow.IsNull ("IsExpression") && (bool) schemaRow ["IsExpression"])
|
||
|
return false;
|
||
|
if (!schemaRow.IsNull ("IsRowVersion") && (bool) schemaRow ["IsRowVersion"])
|
||
|
return false;
|
||
|
if (!schemaRow.IsNull ("IsReadOnly") && (bool) schemaRow ["IsReadOnly"])
|
||
|
return false;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
private bool IncludedInUpdate (DataRow schemaRow)
|
||
|
{
|
||
|
// If the parameter has one of these properties, then we don't include it in the insert:
|
||
|
// AutoIncrement, Hidden, RowVersion
|
||
|
|
||
|
if (!schemaRow.IsNull ("IsAutoIncrement") && (bool) schemaRow ["IsAutoIncrement"])
|
||
|
return false;
|
||
|
if (!schemaRow.IsNull ("IsHidden") && (bool) schemaRow ["IsHidden"])
|
||
|
return false;
|
||
|
if (!schemaRow.IsNull ("IsRowVersion") && (bool) schemaRow ["IsRowVersion"])
|
||
|
return false;
|
||
|
if (!schemaRow.IsNull ("IsExpression") && (bool) schemaRow ["IsExpression"])
|
||
|
return false;
|
||
|
if (!schemaRow.IsNull ("IsReadOnly") && (bool) schemaRow ["IsReadOnly"])
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
private bool IncludedInWhereClause (DataRow schemaRow)
|
||
|
{
|
||
|
if ((bool) schemaRow ["IsLong"])
|
||
|
return false;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
#if ONLY_1_1
|
||
|
private string GetQuotedString (string value)
|
||
|
{
|
||
|
if (value == null || value.Length == 0)
|
||
|
return value;
|
||
|
|
||
|
string prefix = QuotePrefix;
|
||
|
string suffix = QuoteSuffix;
|
||
|
|
||
|
if (prefix.Length == 0 && suffix.Length == 0)
|
||
|
return value;
|
||
|
return String.Format ("{0}{1}{2}", prefix, value, suffix);
|
||
|
}
|
||
|
|
||
|
string GetNullCheckParameterName (string parameterName)
|
||
|
{
|
||
|
return GetParameterName ("IsNull_" + parameterName);
|
||
|
}
|
||
|
|
||
|
|
||
|
private string QuotedTableName {
|
||
|
get { return GetQuotedString (tableName); }
|
||
|
}
|
||
|
|
||
|
public void RefreshSchema ()
|
||
|
{
|
||
|
// FIXME: "Figure out what else needs to be cleaned up when we refresh."
|
||
|
tableName = String.Empty;
|
||
|
dbSchemaTable = null;
|
||
|
deleteCommand = null;
|
||
|
insertCommand = null;
|
||
|
updateCommand = null;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#if NET_2_0
|
||
|
protected override void ApplyParameterInfo (DbParameter parameter,
|
||
|
DataRow datarow,
|
||
|
StatementType statementType,
|
||
|
bool whereClause)
|
||
|
{
|
||
|
SqlParameter sqlParam = (SqlParameter) parameter;
|
||
|
#else
|
||
|
void ApplyParameterInfo (SqlParameter sqlParam,
|
||
|
DataRow datarow,
|
||
|
StatementType statementType,
|
||
|
bool whereClause)
|
||
|
{
|
||
|
#endif
|
||
|
sqlParam.SqlDbType = (SqlDbType) datarow ["ProviderType"];
|
||
|
|
||
|
object precision = datarow ["NumericPrecision"];
|
||
|
if (precision != DBNull.Value) {
|
||
|
short val = (short) precision;
|
||
|
if (val < byte.MaxValue && val >= byte.MinValue)
|
||
|
sqlParam.Precision = (byte) val;
|
||
|
}
|
||
|
|
||
|
object scale = datarow ["NumericScale"];
|
||
|
if (scale != DBNull.Value) {
|
||
|
short val = ((short) scale);
|
||
|
if (val < byte.MaxValue && val >= byte.MinValue)
|
||
|
sqlParam.Scale = (byte) val;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if NET_2_0
|
||
|
protected override
|
||
|
#endif
|
||
|
string GetParameterName (int parameterOrdinal)
|
||
|
{
|
||
|
return String.Format ("@p{0}", parameterOrdinal);
|
||
|
}
|
||
|
|
||
|
#if NET_2_0
|
||
|
protected override
|
||
|
#endif
|
||
|
string GetParameterName (string parameterName)
|
||
|
{
|
||
|
return String.Format ("@{0}", parameterName);
|
||
|
}
|
||
|
|
||
|
#if NET_2_0
|
||
|
protected override string GetParameterPlaceholder (int parameterOrdinal)
|
||
|
{
|
||
|
return GetParameterName (parameterOrdinal);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#endregion // Methods
|
||
|
|
||
|
#region Event Handlers
|
||
|
|
||
|
void RowUpdatingHandler (object sender, SqlRowUpdatingEventArgs args)
|
||
|
{
|
||
|
#if NET_2_0
|
||
|
base.RowUpdatingHandler (args);
|
||
|
#else
|
||
|
if (args.Command != null)
|
||
|
return;
|
||
|
try {
|
||
|
switch (args.StatementType) {
|
||
|
case StatementType.Insert:
|
||
|
args.Command = GetInsertCommand ();
|
||
|
break;
|
||
|
case StatementType.Update:
|
||
|
args.Command = GetUpdateCommand ();
|
||
|
break;
|
||
|
case StatementType.Delete:
|
||
|
args.Command = GetDeleteCommand ();
|
||
|
break;
|
||
|
}
|
||
|
} catch (Exception e) {
|
||
|
args.Errors = e;
|
||
|
args.Status = UpdateStatus.ErrorsOccurred;
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#if NET_2_0
|
||
|
protected override void SetRowUpdatingHandler (DbDataAdapter adapter)
|
||
|
{
|
||
|
SqlDataAdapter sda = adapter as SqlDataAdapter;
|
||
|
if (sda == null) {
|
||
|
throw new InvalidOperationException ("Adapter needs to be a SqlDataAdapter");
|
||
|
}
|
||
|
|
||
|
if (sda != base.DataAdapter)
|
||
|
sda.RowUpdating += new SqlRowUpdatingEventHandler (RowUpdatingHandler);
|
||
|
else
|
||
|
sda.RowUpdating -= new SqlRowUpdatingEventHandler (RowUpdatingHandler);;
|
||
|
}
|
||
|
|
||
|
protected override DataTable GetSchemaTable (DbCommand srcCommand)
|
||
|
{
|
||
|
using (SqlDataReader rdr = (SqlDataReader) srcCommand.ExecuteReader (CommandBehavior.KeyInfo | CommandBehavior.SchemaOnly))
|
||
|
return rdr.GetSchemaTable ();
|
||
|
}
|
||
|
|
||
|
protected override DbCommand InitializeCommand (DbCommand command)
|
||
|
{
|
||
|
if (command == null) {
|
||
|
command = new SqlCommand ();
|
||
|
} else {
|
||
|
command.CommandTimeout = 30;
|
||
|
command.Transaction = null;
|
||
|
command.CommandType = CommandType.Text;
|
||
|
command.UpdatedRowSource = UpdateRowSource.None;
|
||
|
}
|
||
|
return command;
|
||
|
}
|
||
|
#endif // NET_2_0
|
||
|
|
||
|
#endregion // Event Handlers
|
||
|
}
|
||
|
}
|