0

I'm busy building a custom framework for data retrieval and serialization and I'm running into a problem when defining a proprietary database connection/command/parameter combo. Everything works as expected until I try and add parameters to my custom command object. I have a base class that handles query preparation and execution with a generic function as follows:

/// <summary>
/// Prepares a command for execution.
/// </summary>
/// <typeparam name="C">The type of command to prepare</typeparam>
/// <typeparam name="P">The type of parameters to add to the command</typeparam>
/// <param name="query">The query to be prepared for the command</param>
/// <param name="parameters">Dictionary of parameters to be added to the command</param>
/// <returns>A prepared command to execute against a database</returns>
protected virtual C Prepare<C, P>(string query, Dictionary<string, object> parameters)
    where C : DbCommand, new()
    where P : DbParameter, new()
{
    if (Connection == null)
        throw new System.Exception("Database connector hasn't been initialized yet. Call .Initialize() first.");
    C command = new C()
    {
        CommandText = query,
        Connection = Connection
    };
    if (parameters != null)
    {
        foreach (KeyValuePair<string, object> kvp in parameters)
        {
            command.Parameters.Add(new P() // <-- Breaks right here!
            {
                ParameterName = kvp.Key,
                Value = kvp.Value
            });
        }
        parameters = null;
    }
    return command;
}

I have classes implemented for most of the provider types (Ole, ADO, ODBC, Oracle, etc), but they are based off the standard .NET types provided in the System.Data namespace. I now have a completely custom class that inherits from System.Data.Common.DbCommand that I want to use, but when I try and add parameters (in the Prepare function above) to this new class, I see the Parameters property of my new class is null! It is inherited from the base class and is set to read only, so I can't initialize it on my own. My class is defined as follows:

public sealed class Connection : System.Data.Common.DbConnection

I've tried explicitly overriding the property in my class as public new List<Parameter> Parameters { get; set; } but to no avail - the generic function still uses the base class' Parameters property. The only way to get a handle on the overridden property is to explicitly cast command (in the Prepare function) to my custom type, which is obviously what I don't want to do.

Am I missing something here?

FarligOpptreden
  • 5,013
  • 22
  • 23

2 Answers2

0

OK, I managed to sort out the issue. Can't believe I've been blind to this the whole morning! When implementing a new class that inherits from System.Data.Common.DbCommand you have to override the DbParameterCollection property, among others. In my haste to create the new class I just returned null in the getter of this property and, I assume, that's what the Parameters property uses.

So I just implemented a new class that inherits from System.Data.Common.DbParameterCollection and returned a new instance of that class in my getter and it's working now!

FarligOpptreden
  • 5,013
  • 22
  • 23
0

First, new doesn't override the parameter, it's hiding it. This means that anyone using DbCommand.Parameters will see the original implementation while anyone using your type will see your implementation.

Overriding a property can only be done using the override keyword. In this case, you can't override Parameters because it isn't virtual.

Second, DbCommand.Parameters is just an external interface over the protected abstract DbCommand.DbCommandParameterCollection property. You need to implement this method to return a actual parameter collection.

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
  • Ha! Thanks for that... I managed to sort the issue shortly after I posted the question. I didn't see your answer before I posted my own, but I'll accept yours as correct, just because it was exactly what I ended up doing. :) – FarligOpptreden Aug 08 '14 at 09:44