0

我正忙于构建用于数据检索和序列化的自定义框架,并且在定义专有数据库连接/命令/参数组合时遇到了问题。在我尝试将参数添加到我的自定义命令对象之前,一切都按预期工作。我有一个使用通用函数处理查询准备和执行的基类,如下所示:

/// <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;
}

我为大多数提供程序类型(Ole、ADO、ODBC、Oracle 等)实现了类,但它们基于命名空间中提供的标准 .NET 类型System.Data。我现在有一个完全自定义的类,它继承自我System.Data.Common.DbCommand想要使用的类,但是当我尝试Prepare向这个新类添加参数(在上面的函数中)时,我看到Parameters我的新类的属性是null!它继承自基类并设置为只读,所以我不能自己初始化它。我的班级定义如下:

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

我尝试在我的类中显式覆盖该属性,public new List<Parameter> Parameters { get; set; }但无济于事 - 通用函数仍使用基类的Parameters属性。获得重写属性句柄的唯一方法是显式转换command(在Prepare函数中)到我的自定义类型,这显然是我不想做的。

我在这里错过了什么吗?

4

2 回答 2

0

好的,我设法解决了这个问题。不敢相信我整个早上都对这个视而不见!在实现继承自System.Data.Common.DbCommand您的新类时,您必须覆盖该DbParameterCollection属性等。在我匆忙创建新类时,我刚刚null在该属性的 getter 中返回,我认为这就是该Parameters属性使用的。

所以我刚刚实现了一个新类,它继承自System.Data.Common.DbParameterCollection并在我的 getter 中返回了该类的一个新实例,它现在可以工作了!

于 2014-08-08T09:08:15.717 回答
0

首先,new不覆盖参数,它隐藏它。这意味着使用 DbCommand.Parameters 的任何人都将看到原始实现,而使用您的类型的任何人都将看到您的实现。

覆盖属性只能使用override关键字来完成。在这种情况下,您不能覆盖Parameters,因为它不是虚拟的。

其次,DbCommand.Parameters只是protected abstract DbCommand.DbCommandParameterCollection属性的外部接口。您需要实现此方法以返回实际的参数集合。

于 2014-08-08T09:13:38.873 回答