882 lines
25 KiB
C#
Raw Normal View History

//
// 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
}
}