1

我有以下方法,我在多个地方使用,但它只有几个不同的地方不同,所以我想知道如何重构它,以便我可以将它放在一个公共类中并从那里到处调用它。

public override DataTable GetRecords(QueryContext queryContext, out int totalRecords)
{
    // Build Query
    //Different
    StringBuilder query = new StringBuilder("SELECT * FROM TABLE");
    Dictionary<string, string> parameters = new Dictionary<string, string>();

    if (queryContext.OrderByColumns.Count == 0)
    {
        //Can very in length or number of parameters
        queryContext.OrderByColumns.Add("param_1"); //different
        queryContext.OrderByColumns.Add("param_2"); //different
    }

    if (queryContext.Parameters.Count > 0)
    {
        foreach (QueryParameter p in queryContext.Parameters)
        {
            dataAccess.paramAdd(parameters, query, p.ColumnName, p.Value.ToString());
        }
    }

    // Order By Clause
    query.Append(queryContext.OrderByColumns.GetSqlClause());

    // Apply Limit
    if (queryContext.ApplyLimit)
    {
        query.AppendFormat(" LIMIT {0},{1}", queryContext.Offset, queryContext.Limit);
    }

    //Execute the query.
    DataSet results = dataAccess.ExecuteQuery(query.ToString(), parameters);
    totalRecords = Convert.ToInt32(results.Tables[1].Rows[0][0]);
    return results.Tables[0];
}

其他地方的唯一区别是query变量的值和添加的参数queryContext.OrdByColumn.Add(...)。除此之外,一切都一样。

我的第一个镜头将是做类似的事情:

public override DataTable GetRecords(StringBuilder query, string[] orderByParams, QueryContext queryContext, out int totalRecords)
{

    Dictionary<string, string> parameters = new Dictionary<string, string>();

    if (queryContext.OrderByColumns.Count == 0)
    {
        foreach(var param in orderByParams)
        {
            queryContext.OrderByColumns.Add(param);
        }
    }

    if (queryContext.Parameters.Count > 0)
    {
        foreach (QueryParameter p in queryContext.Parameters)
        {
            dataAccess.paramAdd(parameters, query, p.ColumnName, p.Value.ToString());
        }
    }

    // Order By Clause
    query.Append(queryContext.OrderByColumns.GetSqlClause());

    // Apply Limit
    if (queryContext.ApplyLimit)
    {
        query.AppendFormat(" LIMIT {0},{1}", queryContext.Offset, queryContext.Limit);
    }

    //Execute the query.
    DataSet results = dataAccess.ExecuteQuery(query.ToString(), parameters);
    totalRecords = Convert.ToInt32(results.Tables[1].Rows[0][0]);
    return results.Tables[0];
}

我可以使用 LINQ,所以如果可以改进它,我也欢迎使用它的想法。

4

4 回答 4

1

如果它应该在全球范围内使用,它不应该决定添加什么到queryContext. 这是一个参数,因此调用者应根据需要添加这些参数。我不知道 dataAccess 来自哪里,但同样,应该在外面完成。这让你所剩无几。

public override DataTable GetRecords(WhateverClassThisIs dataAccess, QueryContext queryContext, out int totalRecords)    
{
    // Build Query
    StringBuilder query = new StringBuilder("SELECT * FROM TABLE");
    Dictionary<string, string> parameters = new Dictionary<string, string>();

    // Order By Clause
    query.Append(queryContext.OrderByColumns.GetSqlClause());

    // Apply Limit
    if (queryContext.ApplyLimit)
    {
        query.AppendFormat(" LIMIT {0},{1}", queryContext.Offset, queryContext.Limit);
    }

    //Execute the query.
    DataSet results = dataAccess.ExecuteQuery(query.ToString(), parameters);
    totalRecords = Convert.ToInt32(results.Tables[1].Rows[0][0]);
    return results.Tables[0];
}

这是我的建议。

如果可以从不同的表或其他东西中提取,*那么也应该使用函数的参数来处理,如果不是在调用此函数之前构建基本字符串。您确实命名了它GetRecords,因此它应该做的就是根据您传递的内容获取记录。它不应该根据参数的状态动态构建查询,它应该只使用参数来构建查询,而无需(或很少)做出决策。

编辑

为了使其成为实用功能,它需要执行您可以使其执行的最通用的过程。为这个函数添加任何类型的特殊性将使它不再是一个全局实用程序,而更像是一个专门的实用程序(这很好,如果这真的是你想要的 - 但通用更好,更可重用)。我在答案的原始正文和评论中提到,您需要通过调用者中的参数而不是此函数中的参数来处理您的特殊顺序。毕竟,您已经将 queryContext 传递给此函数。这是使用我正在讨论的调用者的示例:

private void ICallUtiltyFunction()
{
    QueryContext context = new QueryContext(); // I don't know if this is really how to instantiate this object

    // Add these here, because this function knows what it needs and
    // it already created the queryContext object
    context.OrderByColumns.Add("param_1");
    context.OrderByColumns.Add("param_2"); 

    // I also know my limit and start here
    context.Offset = 30;
    context.Limit = 30;

    int totalRecords = 0; // You really don't need this, it's wasteful
    DataTable results = Utilities.GetRecords(dataAccess, context, totalRecords);

    // Use the results now
}
于 2013-05-03T18:16:19.263 回答
0

将查询变量和 param_1、param_2 等作为参数传递给方法。如果有不同数量的参数要传递给 queryContext.OrderByColumns.Add,我会将它们传递到某种列表中并循环遍历它们,而不是为所需的每个参数数量创建方法的覆盖。

于 2013-05-03T18:12:58.467 回答
0

我将传递字符串以在一个变量中创建查询,然后传递一个字符串列表以进入您的queryContext.OrderByColumns.Add("")代码。

public override DataTable GetRecords(QueryContext queryContext, String queryString, List<String> parameters, out int totalRecords)
{
    StringBuilder query = new StringBuilder(queryString);

    if (queryContext.OrderByColumns.Count == 0)
    {
        foreach(String str in params)
        {
            queryContext.OrderByColumns.Add(str);
        }
    }

    .....

}
于 2013-05-03T18:16:09.480 回答
0

您可以为不同的查询参数获取一个字符串数组,例如:

public override DataTable GetRecords(QueryContext queryContext, string[] queryParams, out int totalRecords)
{
    // Build Query
    //Different
    StringBuilder query = new StringBuilder("SELECT * FROM TABLE");
    Dictionary<string, string> parameters = new Dictionary<string, string>();

    if (queryContext.OrderByColumns.Count == 0)
    {
        foreach(string param in queryParams) {
           queryContext.OrderByColumns.Add(param);
         }
    }

   ...

}

于 2013-05-03T18:16:19.540 回答