2015-12-09 2 views
0

Привет Я пытаюсь создать функции CRUD в C#, но застрял на моем первом, который является FetchALL, так как пока он говорит, что не весь путь кода возвращает значение.C# getAll Рекомендации по функциям

Heres моего кода до сих пор

public SqlDataReader FetchAll(string tableName) 
     { 



     using (SqlConnection conn = new SqlConnection(_ConnectionString,)) 
    { 

    string query = "SELECT * FROM " + tableName; 
    SqlCommand command = new SqlCommand(query, conn); 
    using (SqlDataReader reader = command.ExecuteReader()) 
    conn.Open(); 


    conn.Close(); 
      } 
     } 
    } 
} 

Я могу дать вам больше информации, спасибо

+5

Вы никогда не возвращаете ничего, но вы объявили функцию для возврата 'SqlDataReader'. Кроме того, SQL-Injection возможно в 'string query =" SELECT * FROM "+ tableName;'. –

+2

Если вы решили вернуть 'SqlDataReader', убедитесь, что он правильно закрыт и удален вызывающим абонентом, в противном случае легко запустить утечку SQL-соединений. –

+2

Не бойтесь пытаться интерпретировать ошибку самостоятельно. Прочтите его и попытайтесь понять это буквально. Не все пути кода (т. Е. НЕ каждый путь выполнения) возвращают значения. Это можно удовлетворить/решить, если ВСЕ пути возвращают значение.Спросите себя, может ли хотя бы одно заявление о возвращении быть достигнуто все время. Начните с включения одного! –

ответ

5

У вас есть тип возврата SqlDataReader, но вы ничего не возвращаете в своем коде. По крайней мере, вы должны объявить чтения данных и вернуть его так:

public SqlDataReader FetchAll(string tableName) 
{ 
    SqlDataReader reader; 

    using (SqlConnection conn = new SqlConnection(_ConnectionString)) 
    { 

     string query = "SELECT * FROM " + tableName; 

     // added using block for your command (thanks for pointing that out Alex K.) 
     using (SqlCommand command = new SqlCommand(query, conn)) 
     { 
      conn.Open(); // <-- moved this ABOVE the execute line. 
      reader = command.ExecuteReader(); // <-- using the reader declared above. 
      //conn.Close(); <-- not needed. using block handles this for you. 
     } 
    } 

    return reader; 
} 

Примечание, я заметил несколько других проблем, которые я видел, как хорошо, что вы можете увидеть мои комментарии.

Кроме того, я хочу отметить, что-то очень важное: вы всегда должны избегать конкатенации строк в запросах, так как это открывает вам до риска инъекции SQL атаки (как gmiley должным образом указал). В этом случае вы должны создать перечисление, которое содержит значения, связанные со всеми возможными именами таблиц, а затем использовать словарь для поиска имен таблиц на основе их значений перечисления. Если пользователь предоставляет недопустимое/неизвестное значение, вы должны были бы исключить аргумент.

Это еще не конец ваших проблем (как указывал По умолчанию). Вы не можете создать соединение в блоке using, который будет располагаться и закрываться, как только он выйдет из блока, а затем использовать , который возвращается из метода. Если бы я был вами, я бы вернул DataSet вместо SqlDataReader. Вот как я это сделать:

Во-первых, создать перечисление возможных значений таблицы:

public enum Table 
{ 
    FirstTable, 
    SecondTable 
} 

и словарь, который отображает значения таблицы перечислений для имен таблиц (которые вы заселяют в вашем статическом конструкторе):

private static Dictionary<Table, string> _tableNames = new Dictionary<Table, string>(); // populate this in your static constructor. 

А то вот ваш метод для извлечения данных:

public static System.Data.DataSet FetchAll(Table fromTable) 
{ 
    var ret = new System.Data.DataSet(); 

    using (var conn = new System.Data.SqlClient.SqlConnection(_connectionString)) 
    { 
     string tableName = ""; 
     if (!_tableNames.TryGetValue(fromTable, out tableName)) throw new ArgumentException(string.Format(@"The table value ""{0}"" is not known.", fromTable.ToString())); 
     string query = string.Format("SELECT * FROM {0}", tableName); 

     using (var command = new System.Data.SqlClient.SqlCommand(query, conn)) 
     { 
      using (var adapter = new System.Data.SqlClient.SqlDataAdapter(command)) 
      { 
       adapter.Fill(ret); 
      } 
     } 
    } 

    return ret; 
} 

. Наконец, я бы посоветовал вам назвать переменные уровня класса с более низким верблюжьим корпусом для каждого соглашения, например. _connectionString.

+1

Я удалил свой ответ, поскольку ваш был чище, так как вы исправляете некоторые из различных проблем, для полноты , Я упомянул пару здесь: SQL Injection - главная проблема с этой функцией, если вам нужно это сделать, поместите имена таблиц в словарь и найдите строковое значение, используя перечисление. Кроме того, этот параметр просто не проверяется перед его использованием. – gmiley

+0

@gmiley - Ах, отличный момент! Я даже не смотрел на фактический SQL. Обновление ... –

+0

Обновлен мой комментарий, чтобы обеспечить решение проблемы с SQL-инъекцией. – gmiley

1

Вам нужны обратные Постулаты для метода, чтобы вернуть значение.

5

Во-первых, вы ничего не возвращаете из метода. Я бы добавил, вы уверены, что хотите вернуть SqlDataReader? Он объявляется внутри блока использования, поэтому он будет закрыт к тому моменту, когда вы его вернете. Я думаю, вы должны переоценить, что должна вернуть эта функция.

+0

Спасибо yer Мне просто нужно вернуть что-то в противном случае fucntion не будет поднято gridview, но я не уверен, что мне нужно вернуть – Lewis

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