Implementing a Custom DataAdapterAs you saw in the previous chapter, the DataAdapter is essentially a plug that takes data from commands and plugs it into DataSets and DataTables. The DataAdapter implementation in this example takes a shortcut and inherits from an abstract base class called DbDataAdapter. The IDbDataAdapter InterfaceThe IDbDataAdapter interface defines the properties listed in Table 28.6. The RDPDataAdapter ClassListing 28.6 illustrates a custom DataAdapter class. Make note of where IDbDataAdapter interface methods are implemented, and where properties and methods from the parent abstract class, DbDataAdapter, are overridden. Listing 28.6. The Remote Data Provider Data Adapter Classusing System; using System.Data; using System.Data.Common; namespace SAMS.CSharpUnleashed.RemoteDataProvider { public class RDPDataAdapter : DbDataAdapter, IDbDataAdapter { private RDPCommand selectCommand; private RDPCommand insertCommand; private RDPCommand deleteCommand; private RDPCommand updateCommand; static private readonly object EventRowUpdated = new object(); static private readonly object EventRowUpdating = new object(); public RDPDataAdapter() { } #region Properties public RDPCommand SelectCommand { get { return selectCommand; } set { selectCommand = value; } } IDbCommand IDbDataAdapter.SelectCommand { get { return selectCommand; } set { selectCommand = (RDPCommand)value; } } public RDPCommand InsertCommand { get { return insertCommand; } set { insertCommand = value; } } IDbCommand IDbDataAdapter.InsertCommand { get { return insertCommand; } set { insertCommand = (RDPCommand)value; } } public RDPCommand UpdateCommand { get { return updateCommand; } set { updateCommand = value; } } IDbCommand IDbDataAdapter.UpdateCommand { get { return updateCommand; } set { updateCommand = (RDPCommand)value; } } public RDPCommand DeleteCommand { get { return deleteCommand; } set { deleteCommand = value; } } IDbCommand IDbDataAdapter.DeleteCommand { get { return deleteCommand; } set { deleteCommand = (RDPCommand)value; } } #endregion override protected RowUpdatedEventArgs CreateRowUpdatedEvent(DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping) { return new RDPRowUpdatedEventArgs(dataRow, command, statementType, tableMapping); } override protected RowUpdatingEventArgs CreateRowUpdatingEvent(DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping) { return new RDPRowUpdatingEventArgs(dataRow, command, statementType, tableMapping); } override protected void OnRowUpdating(RowUpdatingEventArgs value) { RDPRowUpdatingEventHandler handler = (RDPRowUpdatingEventHandler) Events[EventRowUpdating]; if ((null != handler) && (value is RDPRowUpdatingEventArgs)) { handler(this, (RDPRowUpdatingEventArgs) value); } } override protected void OnRowUpdated(RowUpdatedEventArgs value) { RDPRowUpdatedEventHandler handler = (RDPRowUpdatedEventHandler) Events[EventRowUpdated]; if ((null != handler) && (value is RDPRowUpdatedEventArgs)) { handler(this, (RDPRowUpdatedEventArgs) value); } } public event RDPRowUpdatingEventHandler RowUpdating { add { Events.AddHandler(EventRowUpdating, value); } remove { Events.RemoveHandler(EventRowUpdating, value); } } public event RDPRowUpdatedEventHandler RowUpdated { add { Events.AddHandler(EventRowUpdated, value); } remove { Events.RemoveHandler(EventRowUpdated, value); } } } public delegate void RDPRowUpdatingEventHandler(object sender, RDPRowUpdatingEventArgs e); public delegate void RDPRowUpdatedEventHandler(object sender, RDPRowUpdatedEventArgs e); public class RDPRowUpdatingEventArgs : RowUpdatingEventArgs { public RDPRowUpdatingEventArgs(DataRow row, IDbCommand command, StatementType statementType, DataTableMapping tableMapping) : base(row, command, statementType, tableMapping) { } // Hide the inherited implementation of the command property. new public RDPCommand Command { get { return (RDPCommand)base.Command; } set { base.Command = value; } } } public class RDPRowUpdatedEventArgs : RowUpdatedEventArgs { public RDPRowUpdatedEventArgs(DataRow row, IDbCommand command, StatementType statementType, DataTableMapping tableMapping) : base(row, command, statementType, tableMapping) { } // Hide the inherited implementation of the command property. new public RDPCommand Command { get { return (RDPCommand)base.Command; } } } } As you've seen in the preceding listings, the framework for creating your own data provider is already in place and written for you within ADO.NET. With a little imagination and a connection-style data source, you can create some extremely flexible and compelling code with your own custom data providers. |