我怎样才能重构这个方法,所以我不在多个地方使用它?

时间:2013-05-03 18:06:51

标签: c#

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

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 个答案:

答案 0 :(得分: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
}

答案 1 :(得分:0)

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

答案 2 :(得分: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);
        }
    }

    .....

}

答案 3 :(得分: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);
         }
    }

   ...

}