ibrahim maher Ответов: 2

Как сделать так, чтобы метод в классе возвращал сообщение


В С#
У меня есть класс, который можно выбрать из таблицы базы данных, отправив некоторый параметр этому методу
когда возникает ошибка, Я хочу получить сообщение.

Я сделал этот класс, но чтобы сохранить сообщение об ошибке, я сделал переменную REF!

любой другой способ заменить переменную Ref нормальной переменной или любыми новыми методами

Что я уже пробовал:

public class DataManager
    {

        public bool SelectFromTable(ref string SQLErr, SqlConnection cnn, string 
                                    SQLString, DataSet ds, string dataTabelName)
        {
            try
            {
               
                SqlDataAdapter da = new SqlDataAdapter(@"Select " + SQLString, cnn);
               
                da.Fill(ds, dataTabelName);

                if (ds.Tables[dataTabelName].DefaultView.Count == 0)
                {
                    return false;

                }
                else
                {
                    return true;

                }

            }
            catch(Exception e)
            {
                SQLErr=e.Message.ToString();
                return false;
            }
            
        }

2 Ответов

Рейтинг:
5

Richard Deeming

Код, который вы показали, предполагает, что вы пишете код, который уязвим для SQL-инъекция[^]. Вы не предоставили никаких средств для передачи параметров в запрос, а это означает, что вам придется использовать конкатенацию строк для передачи их в SQL. Помимо проблемы, с которой вы столкнетесь, пытаясь получить правильный формат, вы оставляете свою базу данных широко открытой для случайного или преднамеренного уничтожения.

Измените свой код, чтобы правильно передавать параметры. И не ловите исключение в своем методе; пусть оно распространяется на вызывающий метод, чтобы его можно было поймать кодом, который знает, как с ним справиться.

public static class DataManager
{
    private static void PrepareCommand(SqlCommand command, string query, object[] parameters)
    {
        if (parameters != null && parameters.Length != 0)
        {
            if (parameters.All(p => p is SqlParameter))
            {
                command.Parameters.AddRange(parameters);
            }
            else if (parameters.Any(p => p is SqlParameter))
            {
                throw new InvalidOperationException("Cannot mix SqlParameter and raw value parameters.");
            }
            else
            {
                string[] parameterNames = new string[parameters.Length];
                for (int index = 0; index < parameters.Length; index++)
                {
                    string name = "@p" + index;
                    parameterNames[index] = name;
                    command.Parameters.AddWithValue(name, parameters[index] ?? DBNull.Value);
                }
                
                query = string.Format(CultureInfo.InvariantCulture, query, parameterNames);
            }
        }
        
        command.CommandText = query;
    }
    
    public static bool SelectFromTable(SqlConnection connection, string query, DataSet ds, string dataTableName, params object[] parameters)
    {
        if (connection == null) throw new ArgumentNullException(nameof(connection));
        if (string.IsNullOrEmpty(query)) throw new ArgumentNullException(nameof(query));
        if (ds == null) throw new ArgumentNullException(nameof(ds));
        if (string.IsNullOrEmpty(dataTableName)) throw new ArgumentNullException(nameof(dataTableName));
        
        using (var command = new SqlCommand(null, connection))
        {
            PrepareCommand(command, query, parameters);
            
            var dataAdapter = new SqlDataAdapter(command);
            dataAdapter.Fill(ds, dataTableName);
        }
        
        return ds.Tables[dataTableName].DefaultView.Count != 0;
    }
}

Затем вы можете правильно передать параметры в запрос:
private void btnOpenTable_Click(object sender, EventArgs e)
{
    try
    {
        var ds = new DataSet();
        string query = "SELECT Name, MainCode FROM banna.dbo.chartofaccounts WHERE MainCode Like {0} And db_confirm != {1} ORDER BY MainCode";
        if (DataManager.SelectFromTable(cnMain, query, ds, "T", txtMainCode.Text, txtConfirm.Text))
        {
            DataTable dt = ds.Tables[0];
            textBox1.Text = Convert.ToString(dt.Rows[0]["name"]);
            dataGridView1.DataSource = dt;
        }
    }
    catch (SqlException ex)
    {
        MessageBox.Show(ex.Message);
    }
}

Кроме того, вы можете пройти SqlParameter объекты:
string query = "SELECT Name, MainCode FROM banna.dbo.chartofaccounts WHERE MainCode Like @MainCode And db_confirm != @Confirm ORDER BY MainCode";

var parameters = new[] 
{ 
    new SqlParameter("@MainCode", txtMainCode.Text),
    new SqlParameter("@Confirm", txtConfirm.Text)
};

if (DataManager.SelectFromTable(cnMain, query, ds, "T", parameters))
...



Все, что вы хотели знать о SQL-инъекции (но боялись спросить) | Трой Хант[^]
Как я могу объяснить SQL-инъекцию без технического жаргона? | Обмен Стеками Информационной Безопасности[^]
Шпаргалка по параметризации запросов / OWASP[^]


ibrahim maher

спасибо за помощь
Я Моифаю свой код следующим образом :

открытый класс DataManager
{
SelectFromTable общественная bool( sqlconnection с CNN, что строки типа sqlstring, набора ДС DataTabelName строку,слово params объекта[] параметр)
{

Команда SqlCommand = новая команда SqlCommand();
команда.Соединение = cnn;

int i = 0;
string[] ParameterName=новая строка[Paramter.Длина];

если (параметр.Длина != 0)
{
по каждому элементу (строка пар в параметр)
{
имя строки = "@p " + i;
ParameterName[i] = имя;
команда.Параметры.AddWithValue(имя, пар);
я++;
}

SQLString = строка.Формат (CultureInfo.Языка И Региона Существует, Типа Sqlstring, Имяпараметра);
}

команда.CommandText = "Select" + SQLString;

SqlDataAdapter da = новый SqlDataAdapter(команда);

da. Fill(ds, DataTabelName);

если (ДС.Таблицы[DataTabelName].DefaultView.Count = = 0)
возвращать false;
еще
вернуть true;

}

это хорошо и получится

но я не понимаю смысла утверждения:

SQLString = строка.Формат (CultureInfo.Языка И Региона Существует, Типа Sqlstring, Имяпараметра);
- космическая культура.Языка и региона существует-

Рейтинг:
1

OriginalGriff

Один ref переменная-это "нормальная переменная" - просто вы можете изменить значение во внешнем мире, установив его внутри метода. Есть только два способа сделать это: ref и out переменные.
Единственный другой способ сделать это-изменить возвращаемое значение из bool на пользовательский класс, пару ключ/значение, кортеж или строку, которую вы возвращаете как null для "no error".

Но обратите внимание, что в вашем коде, когда вы возвращаете false, вы не всегда устанавливаете сообщение об ошибке ...

Гораздо лучшим подходом было бы сделать его void метод и выбрасывать исключение, когда вы сталкиваетесь с проблемой.


ibrahim maher

спасибо за помощь...
У меня есть 2 вопроса?
1-Если я преобразую метод в метод void, откуда я знаю, что оператор Select возвращает данные или нет?
2-я проверил ошибку при запуске метода в основном классе, если я сделал класс для получения ошибки, должен ли этот класс запускаться после основного класса?

ibrahim maher

это мой код при передаче параметра
частная btnOpenTable_Click недействительным(объект отправителя, EventArgs в электронной)
{

строки типа sqlstring;

DataTable dt = новый DataTable();
типа sqlstring = "наименование,MainCode от Банна.ДБО.chartofaccounts где maincode, как '1%' и db_confirm&ЛТ;&ГТ;'=' приказ MainCode";

if (vDataManager.SelectFromTable(ref errMeaage, cnMain, sqlString, ds, "T"))
{
ДТ = ДС.Столы["Т"];
текстовое поле textbox1.Текст = ДТ.Строки[0]["имя"].Метод toString();
dataGridView1.Источник данных = ДТ;

}
еще
{
if (errMeaage != null) {MessageBox.Show (errMeaage);} else { errMeaage = null; }
}

}