Оператор запроса работает на SQL сервере, но не работает на C# - PullRequest
0 голосов
/ 29 мая 2020

У меня есть этот запрос.

SELECT DISTINCT 
    nome as Nome, Cognome As Cognome, DataConsegna as Data, 
    'RichiesteAttrezzatura' [Tipo Richiesta] 
FROM 
    RichiesteAttrezzatura 

UNION 

SELECT DISTINCT 
    nome AS Nome, Cognome as Cognome, DataConsegna as Data, 
    'RichiesteMateriali' [Tipo Richiesta] 
FROM 
    RichiesteMateriali 

UNION 

SELECT DISTINCT 
    nome AS Nome, Cognome as Cognome, giorno AS Data, 
    'RichiesteVestiario' [Tipo Richiesta] 
FROM 
    RichiesteVestiario

Как и в заголовке, проблема в том, что он работает на SQL сервере, когда я его выполняю, но когда я пытаюсь выполнить C#, он просто возвращает пустой таблица.

Из того, что я понял, глядя на net и на этом форуме проблема связана с одинарными кавычками.

Это моя функция

adonet db;

DataProvider()
{ 
    db = new adonet();
    db.CreaConnessione();
}

public DataTable getRichiesteForDGV(int id)
{
    DataTable dt = new DataTable();

    string richiesteVestiario = "RichiesteVestiario";
    string richiesteMateriali = "RichiesteMateriali";
    string richiesteAttrezzatura = "RichiesteAttrezzatura";

    string sql = "SELECT DISTINCT nome as Nome, Cognome As Cognome, DataConsegna as Data, '" + richiesteAttrezzatura + "' [Tipo Richiesta] FROM RichiesteAttrezzatura " +
                "UNION SELECT DISTINCT nome AS Nome, Cognome as Cognome, DataConsegna as Data, '" + richiesteMateriali + "' [Tipo Richiesta] FROM RichiesteMateriali " +
                "UNION SELECT DISTINCT nome AS Nome, Cognome as Cognome, giorno AS Data, '" + richiesteVestiario + "' [Tipo Richiesta] FROM RichiesteVestiario";

    db.EseguiQueryWithParams(sql, new SqlParameter("@id", id));

    return dt;
}

public DataTable EseguiQueryWithParams(string sql, params SqlParameter[] parameters)
    {
        ApriConnessione();
        string nometab = "dump";
        cmd.CommandText = sql;

        cmd.CommandType = System.Data.CommandType.Text;
        cmd.Parameters.AddRange(parameters);
        try
        {
            adp = new SqlDataAdapter(cmd);
            if (dset.Tables[nometab] != null)
                dset.Tables[nometab].Clear();

            adp.Fill(dset, nometab);
            DataTable d = dset.Tables[nometab];
            //d.Columns;
            return d;
        }
        catch (Exception e)
        {
            throw e;
            //throw new System.Exception("Errore nella lettura della tabella");

        }
        finally
        {
            adp.Dispose();
            cmd.Dispose();
            ChiudiConnessione();
        }

    }

Any помощь приветствуется. Я обновил пост, так как понял, что проблема в моем C#

1 Ответ

3 голосов
/ 29 мая 2020

Во-первых, я собираюсь потратить минуту, предлагая некоторые изменения в EseguiQueryWithParams(), которые слишком велики, чтобы уместиться в качестве комментария.

Для начала, способ, которым он обрабатывает соединение , не Хорошая практика. Прочтите ссылку, пока не поймете. Вместо этого вам нужен общий метод или свойство, которое сообщает вам строку подключения и ничего больше. Все остальные изменения в методе должны быть понятны в коде:

private DataTable EseguiQuery(string sql, params SqlParameter[] parameters)
{
    // The method should only supply the string. 
    // DO NOT TRY TO REUSE THE SAME CONNECTION OBJECT!
    string connectionString = Connessione();
    var dset = new DataSet(); //creating a new dataset for this query also means there's no need to check and clear it further down

    //Using blocks guarantee the items are disposed, even if an exception is thrown
    using (var connection = new SqlConnection(connectionString))
    using (var cmd = new SqlCommand(sql, connection))
    using (var adp = new SqlDataAdapater(cmd))
    {
        cmd.CommandText = sql; //cmd.CommandType already has "Text" as the default value
        if (parameters is object && parameters.Length > 0)
        {   //conditional test lets us skip the parameters argument when calling the method
            cmd.Parameters.AddRange(parameters);
        }
        adp.Fill(dset); // Fill() opens and closes the connection automatically
        return dset.Tables[0]; 
    }
} // No try/catch anywhere, because the old try/catch didn't do anything

Посмотрите, насколько меньше кода (17 строк против 31 после очистки комментариев), но он выполняет все те же действия. . Прикрывается даже открытие и закрытие соединения, даже менее очевидно где. Кроме того, он позволяет пропускать параметры передачи, например:

var result = db.EseguiQuery(sql)

Еще одно важное изменение - сделать этот метод закрытым . Сделайте то же самое для других методов Execute / Ese gui. getRichiesteForDGV(), а также другие методы, которые взаимодействуют с БД, также должны быть (publi c) членами типа, представленного переменной db. Таким образом, вы получаете хорошее разделение проблем между вашим доступом к данным и вашим пользовательским интерфейсом. В вашем приложении нет возможности получить доступ к базе данных без использования члена publi c этого типа.

Наконец, я удалил часть имени WithParams, поскольку считаю, что предоставление перегрузка, которая их не ожидает. Параметры настолько важны, что вы хотите, чтобы разработчикам было понятно, что они будут их использовать. И поскольку имя таблицы на самом деле не важно, и вы можете вызывать хранимые процедуры со стандартным Text CommandType, задав им перед ними exec, это может полностью заменить старый метод ExecuteQuery().


После всего этого мы, наконец, можем обратиться к самому вопросу. EseguiQueryWithParams() возвращает DataTable, но это возвращаемое значение игнорируется. Это никогда не связано с переменной dt, объявленной и возвращенной в getRichiesteForDGV(). Исправьте это вместе с моими предлагаемыми изменениями, например:

public DataTable getRichiesteForDGV(int id)
{
    string richiesteVestiario = "RichiesteVestiario";
    string richiesteMateriali = "RichiesteMateriali";
    string richiesteAttrezzatura = "RichiesteAttrezzatura";

    string sql = $"SELECT DISTINCT nome as Nome, Cognome As Cognome, DataConsegna as Data, '{richiesteAttrezzatura}' [Tipo Richiesta] FROM RichiesteAttrezzatura " +
                "UNION SELECT DISTINCT nome AS Nome, Cognome as Cognome, DataConsegna as Data, '{richiesteMateriali}' [Tipo Richiesta] FROM RichiesteMateriali " +
                "UNION SELECT DISTINCT nome AS Nome, Cognome as Cognome, giorno AS Data, '{richiesteVestiario}' [Tipo Richiesta] FROM RichiesteVestiario";

    // this should be a member of the `db` class now, so "db." is implied
    return EseguiQuery(sql);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...