Implementing a Custom CommandWhen you think about implementing a custom data provider, you should usually start your thinking at the command level. The command is the workhorse of the entire provider. When a DataAdapter fills a DataSet, it uses a command to generate a DataReader that is then used to populate the DataSet. The command utilizes the existing connection to perform the actual data operation, including sending parameters, obtaining results, and populating output parameters. The IDbCommand InterfaceThe IDbCommand interface defines the properties and methods listed in Table 28.4. The RDPCommand ClassListing 28.4 shows the implementation of IDbCommand, the RDPCommand class. Listing 28.4. The Remote Data Provider Command Classusing System; using System.Data; namespace SAMS.CSharpUnleashed.RemoteDataProvider { public class RDPCommand : IDbCommand { private RDPConnection connection = null; private string cmdText; private RDPParameterCollection parameters = null; private UpdateRowSource urs; public RDPCommand() { cmdText = ""; } public RDPCommand(string commandText) { cmdText = commandText; } public RDPCommand( string commandText, RDPConnection connection ) { cmdText = commandText; this.connection = connection; } #region IDbCommand Members public void Cancel() { throw new NotSupportedException("Cancel method not supported by the RDP."); } public void Prepare() { throw new NotSupportedException("Prepare method not supported by the RDP."); } public System.Data.CommandType CommandType { get { return CommandType.Text; } set { if (value != CommandType.Text) throw new NotSupportedException("Only text commands are supported by the RDP Provider."); } } private RDPDataReader GetReader() { DataSet ds; int rowsAffected; RemoteDataHost.DataHost dhProxy = new RemoteDataHost.DataHost(); dhProxy.Url = connection.ConnectionString; ds = dhProxy.ExecuteDataSet( cmdText, out rowsAffected ); RDPDataReader reader = new RDPDataReader( ds.Tables[0] , connection ); return reader; } public RDPDataReader ExecuteReader(System.Data.CommandBehavior behavior) { return GetReader(); } IDataReader System.Data.IDbCommand.ExecuteReader( System.Data.CommandBehavior behavior) { return (IDataReader)GetReader(); } IDataReader System.Data.IDbCommand.ExecuteReader() { return (IDataReader)GetReader(); } public object ExecuteScalar() { DataSet ds; int rowsAffected; RemoteDataHost.DataHost dhProxy = new RemoteDataHost.DataHost(); dhProxy.Url = connection.ConnectionString; ds = dhProxy.ExecuteDataSet( cmdText, out rowsAffected ); return ds.Tables[0].Rows[0][0]; } public int ExecuteNonQuery() { DataSet ds; int rowsAffected; RemoteDataHost.DataHost dhProxy = new RemoteDataHost.DataHost(); dhProxy.Url = connection.ConnectionString; ds = dhProxy.ExecuteDataSet( cmdText, out rowsAffected ); return rowsAffected; } public int CommandTimeout { get { return 0; } set { } } public IDbDataParameter CreateParameter() { return (IDbDataParameter)(new RDPParameter()); } public IDbConnection Connection { get { return connection; } set { connection = (RDPConnection)value; } } public System.Data.UpdateRowSource UpdatedRowSource { get { return urs; } set { urs = value; } } public string CommandText { get { return cmdText; } set { cmdText = value; } } public IDataParameterCollection Parameters { get { return parameters; } } public IDbTransaction Transaction { get { throw new NotSupportedException("Transactions not supported by RDP."); } set { throw new NotSupportedException("Transactions not supported by RDP."); } } #endregion #region IDisposable Members public void Dispose() { this.Dispose(true); System.GC.SuppressFinalize(this); } private void Dispose(bool disposing) { // get rid of any resources that need to be disposed } #endregion } } |