2013-05-03 3 views
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 и paramters добавленные 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 доступна для меня, так что если это может улучшить его, я приветствовать идеи с помощью этого тоже.

+3

Это могло бы быть лучше подходит для codereview.stackexchange.com. –

+0

Как отличается переменная 'query'? Кроме того, почему у вас есть параметр out для общих записей? Вы можете просто подсчитать записи в возвращаемом 'DataTable'. –

+0

@DaveZych - В зависимости от таблицы, которую я выбираю, она обычно будет отличаться чем-то вроде «SELECT * FROM People WHERE» или «SELECT * FROM Countries WHERE» и т. Д. – Xaisoft

ответ

0

Передайте переменную запроса и param_1, param_2 и т. Д. В качестве параметров метода. Если переменное количество параметров передается в queryContext.OrderByColumns.Add, я передал бы их в какой-то список и пропустил бы их через них, вместо того, чтобы создавать переопределения метода для каждого количества необходимых параметров.

+0

Управление параметром должно выполняться вызывающим абонентом, а не вызываемым, если он не будет «базой» для вызова. –

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

    ..... 

} 
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, и поэтому все, что он должен делать, это выборка записей на основе того, что вы передаете. Он не должен динамически строить запрос на основе состояния аргументов, он должен просто использовать аргументы для построения запроса без (или с очень небольшим) принятием решений.

EDIT

Для того, чтобы сделать эту утилиту функцию а она должна выполнить наиболее общий процесс, который вы можете сделать его выполнить. Чтобы добавить какую-либо специфику к этой функции, она будет меньше глобальной полезности и больше специализированной утилиты (это нормально, если это действительно то, что вы хотите, но общее лучше и многократно используется повторно). Я упомянул в исходном тексте ответа и в комментариях, что вам нужно обрабатывать специализированный порядок по параметрам в вызывающем, а не в этой функции. В конце концов, вы уже передаете 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 
} 
+0

dataAccess - глобальная переменная вне метода. – Xaisoft

+0

Что вы делали с добавлением порядка по параметрам? – Xaisoft

+1

@Xaisoft Я знаю, что это на основе вашего образца. Если вы хотите сделать эту утилиту в отдельном классе, вам необходимо передать ее. –

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

    ... 

}

Смежные вопросы