|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using System.Threading.Tasks;
namespace System.Data.Common
{
public abstract class DbCommand : Component, IDbCommand, IAsyncDisposable
{
protected DbCommand() : base()
{
}
[DefaultValue("")]
[RefreshProperties(RefreshProperties.All)]
[AllowNull]
public abstract string CommandText { get; set; }
public abstract int CommandTimeout { get; set; }
[DefaultValue(System.Data.CommandType.Text)]
[RefreshProperties(RefreshProperties.All)]
public abstract CommandType CommandType { get; set; }
[Browsable(false)]
[DefaultValue(null)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DbConnection? Connection
{
get { return DbConnection; }
set { DbConnection = value; }
}
IDbConnection? IDbCommand.Connection
{
get { return DbConnection; }
set { DbConnection = (DbConnection?)value; }
}
protected abstract DbConnection? DbConnection { get; set; }
protected abstract DbParameterCollection DbParameterCollection { get; }
protected abstract DbTransaction? DbTransaction { get; set; }
// By default, the cmd object is visible on the design surface (i.e. VS7 Server Tray)
// to limit the number of components that clutter the design surface,
// when the DataAdapter design wizard generates the insert/update/delete commands it will
// set the DesignTimeVisible property to false so that cmds won't appear as individual objects
[DefaultValue(true)]
[DesignOnly(true)]
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public abstract bool DesignTimeVisible { get; set; }
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DbParameterCollection Parameters => DbParameterCollection;
IDataParameterCollection IDbCommand.Parameters => DbParameterCollection;
[Browsable(false)]
[DefaultValue(null)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DbTransaction? Transaction
{
get { return DbTransaction; }
set { DbTransaction = value; }
}
IDbTransaction? IDbCommand.Transaction
{
get { return DbTransaction; }
set { DbTransaction = (DbTransaction?)value; }
}
[DefaultValue(System.Data.UpdateRowSource.Both)]
public abstract UpdateRowSource UpdatedRowSource { get; set; }
internal void CancelIgnoreFailure()
{
// This method is used to route CancellationTokens to the Cancel method.
// Cancellation is a suggestion, and exceptions should be ignored
// rather than allowed to be unhandled, as the exceptions cannot be
// routed to the caller. These errors will be observed in the regular
// method instead.
try
{
Cancel();
}
catch (Exception)
{
}
}
public abstract void Cancel();
public DbParameter CreateParameter() => CreateDbParameter();
IDbDataParameter IDbCommand.CreateParameter() => CreateDbParameter();
protected abstract DbParameter CreateDbParameter();
protected abstract DbDataReader ExecuteDbDataReader(CommandBehavior behavior);
public abstract int ExecuteNonQuery();
public DbDataReader ExecuteReader() => ExecuteDbDataReader(CommandBehavior.Default);
IDataReader IDbCommand.ExecuteReader() => ExecuteDbDataReader(CommandBehavior.Default);
public DbDataReader ExecuteReader(CommandBehavior behavior) => ExecuteDbDataReader(behavior);
IDataReader IDbCommand.ExecuteReader(CommandBehavior behavior) => ExecuteDbDataReader(behavior);
public Task<int> ExecuteNonQueryAsync() => ExecuteNonQueryAsync(CancellationToken.None);
public virtual Task<int> ExecuteNonQueryAsync(CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{
return ADP.CreatedTaskWithCancellation<int>();
}
else
{
CancellationTokenRegistration registration = default;
if (cancellationToken.CanBeCanceled)
{
registration = cancellationToken.Register(s => ((DbCommand)s!).CancelIgnoreFailure(), this);
}
try
{
return Task.FromResult(ExecuteNonQuery());
}
catch (Exception e)
{
return Task.FromException<int>(e);
}
finally
{
registration.Dispose();
}
}
}
public Task<DbDataReader> ExecuteReaderAsync() =>
ExecuteReaderAsync(CommandBehavior.Default, CancellationToken.None);
public Task<DbDataReader> ExecuteReaderAsync(CancellationToken cancellationToken) =>
ExecuteReaderAsync(CommandBehavior.Default, cancellationToken);
public Task<DbDataReader> ExecuteReaderAsync(CommandBehavior behavior) =>
ExecuteReaderAsync(behavior, CancellationToken.None);
public Task<DbDataReader> ExecuteReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken) =>
ExecuteDbDataReaderAsync(behavior, cancellationToken);
protected virtual Task<DbDataReader> ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{
return ADP.CreatedTaskWithCancellation<DbDataReader>();
}
else
{
CancellationTokenRegistration registration = default;
if (cancellationToken.CanBeCanceled)
{
registration = cancellationToken.Register(s => ((DbCommand)s!).CancelIgnoreFailure(), this);
}
try
{
return Task.FromResult<DbDataReader>(ExecuteReader(behavior));
}
catch (Exception e)
{
return Task.FromException<DbDataReader>(e);
}
finally
{
registration.Dispose();
}
}
}
public Task<object?> ExecuteScalarAsync() =>
ExecuteScalarAsync(CancellationToken.None);
public virtual Task<object?> ExecuteScalarAsync(CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{
return ADP.CreatedTaskWithCancellation<object?>();
}
else
{
CancellationTokenRegistration registration = default;
if (cancellationToken.CanBeCanceled)
{
registration = cancellationToken.Register(s => ((DbCommand)s!).CancelIgnoreFailure(), this);
}
try
{
return Task.FromResult<object?>(ExecuteScalar());
}
catch (Exception e)
{
return Task.FromException<object?>(e);
}
finally
{
registration.Dispose();
}
}
}
public abstract object? ExecuteScalar();
public abstract void Prepare();
public virtual Task PrepareAsync(CancellationToken cancellationToken = default)
{
if (cancellationToken.IsCancellationRequested)
{
return Task.FromCanceled(cancellationToken);
}
try
{
Prepare();
return Task.CompletedTask;
}
catch (Exception e)
{
return Task.FromException(e);
}
}
public virtual ValueTask DisposeAsync()
{
Dispose();
return default;
}
}
}
|