Implementing IDataParameter and IDataParameterCollectionThe first items to deal with when creating the custom provider are parameters. Parameters are associated with commands and can be input parameters, output parameters, or both. Those parameters are associated with data commands via a customized collection of parameters. The IDataParameter InterfaceThe IDataParameter interface is fairly simple. Table 28.1 lists the properties defined by the IDataParameter interface. The IDataParameterCollection InterfaceThe IDataParameterCollection isn't much more than a marker interface. It is used to tell the custom provider that the collection of parameters supports a minimal set of collection functionality. Table 28.2 lists the properties and methods defined by the IDataParameterCollection interface. The RDPParameter ClassNow that you've seen the basic interfaces that will be implemented, take a look at the code. The code in Listing 28.1 shows the RDPParameter class. If you really feel like typing this all in (as opposed to copying it from the book's media), create a new C# Class library called RemoteDataProvider and add the RDPParameter class as shown here. Listing 28.1. The Remote Data Provider Parameter Classusing System; using System.Data; namespace SAMS.CSharpUnleashed.RemoteDataProvider { public class RDPParameter : IDataParameter { private DbType dbType; private ParameterDirection direction = ParameterDirection.Input; private string paramName; private string sourceColumn; private object paramValue; private DataRowVersion sourceRowVersion = DataRowVersion.Current; public RDPParameter() { } public RDPParameter( string parameterName, DbType type) { paramName = parameterName; dbType = type; } public RDPParameter( string parameterName, object value ) { paramName = parameterName; paramValue = value; } public RDPParameter( string parameterName, DbType type, string sourceColumn ) { paramName = parameterName; dbType = type; this.sourceColumn = sourceColumn; } #region IDataParameter Members public System.Data.ParameterDirection Direction { get { return direction; } set { direction = value; } } public System.Data.DbType DbType { get { return dbType; } set { dbType = value; } } public object Value { get { return paramValue; } set { paramValue = value; } } public bool IsNullable { get { return false; } } public System.Data.DataRowVersion SourceVersion { get { return sourceRowVersion; } set { sourceRowVersion = value; } } public string ParameterName { get { return paramName; } set { paramName = value; } } public string SourceColumn { get { return sourceColumn; } set { sourceColumn = value; } } #endregion } } You might have noticed that this class isn't doing anything special or unusual. The code just provides a stock implementation of the appropriate interfaces for most of the interfaces discussed in this chapter. There are two reasons for creating the custom implementation: to show you a sample implementation, and so that if you want to customize any of this later, you can simply take the provided implementation and add to it without much effort. The RDPParameterCollection ClassThe RDPParameterCollection class shown in Listing 28.2 is just as simple as the RDPParameter class, if not simpler. It provides a simple ArrayList implementation to store the list of RDPParameter instances to be used for an RDPCommand. Listing 28.2. The Remote Data Provider Parameter Collection Classusing System; using System.Data; using System.Collections; namespace SAMS.CSharpUnleashed.RemoteDataProvider { public class RDPParameterCollection : ArrayList, IDataParameterCollection { public RDPParameterCollection() : base() {} #region IDataParameterCollection Members public object this[string parameterName] { get { return this[IndexOf(parameterName)]; } set { this[IndexOf(parameterName)] = value; } } public void RemoveAt(string parameterName) { RemoveAt(IndexOf(parameterName)); } public bool Contains(string parameterName) { return ( -1 != IndexOf(parameterName) ); } public int IndexOf(string parameterName) { int idx = 0; foreach (RDPParameter param in this) { if ( parameterName == param.ParameterName) return idx; idx ++; } return -1; } #endregion public override bool IsReadOnly { get { return false; } } public override int Add(object value) { return Add((RDPParameter)value); } public int Add( RDPParameter value) { if (value.ParameterName != null) return base.Add(value); else throw new ArgumentException("RDP Parameter must have a name"); } public int Add( string parameterName, DbType dbType ) { return Add ( new RDPParameter( parameterName, dbType ) ); } public int Add( string parameterName, object value ) { return Add( new RDPParameter( parameterName, value) ); } public int Add( string parameterName, DbType type, string sourceColumn ) { return Add( new RDPParameter( parameterName, type, sourceColumn ) ); } } } As you can see, it's a pretty simple class. All it's really doing is providing an implementation of the interface and some strongly typed implementations of the collection methods to make things easy for other programmers to use. |