Azure Programowanie

Pobieranie danych z MS SQL w Azure Function

Czasami pojawia sie potrzeba skorzystania w Azure Functions z danych znajdujących się w „starożytnych” 1 bazach SQL. Nie żadnym noSQL jak Cosmos DB, czy Storage Tables. Zapewne można w tym momencie skorzystać z ADO.NET, czy innej biblioteki wykorzystywanej w dużych systemach. Ale funkcje raczej potrzebują czegoś lekkiego I szybkiego. I tutaj z pomoca przychodzi nam biblioteka System.Data.SqlClient.

Staram się w funkcjach nie pisać całych zapytań a tylko korzystać z widoków, czy procedur zapisanych na bazie. Ułatwia to proces developmentu. Między innymi dzięki temu, że przy zmianie warunków WHERE czy ORDER nie musimy wdrażać od nowa całej Function APP. Wystarczy tylko zrobić ALTER na procedurze czy widoku i voila.

SQL bez wyniku

// Disclaimer: Używam pre-kompilowanych funkcji pisanych w Visual studio a nie C# scripts (pliki .csx). Dla tej drugiej metody kod będzie się trochę różnić.
Connection string do bazy dancyh na której chcę wykonywać zapytania znajduje się w App Settings o nazwie DBConnection.

// nie zapomnijmy dodać using na górze pliku funkcji
using System.Data.SqlClient;

// w ciele metody wystarczy użyć poniższego kodu:
var id = 4;
using (SqlConnection conn = new SqlConnection(config["DBConnection"]))
{
    conn.Open();

    var setStartProcessCommand = $"EXEC dbo.SetStartProcessDate @Id='{id}'";

    using (SqlCommand cmd = new SqlCommand(setStartProcessCommand, conn))
    {
        var rows = await cmd.ExecuteNonQueryAsync();
    }
}        

Powyższy kod wykonuje tylko procedurę na bazie. Procedura ta dokonuje zmian na danych w tabeli lub tabelach. Natomiast z punktu widzenia funkcji nie interesuje nas zwracany wynik (o ile jakikolwiek jest). Stąd też użycie metody ExecuteNonQueryAsync(). NonQuery czyli właśnie nie odczytujemy wyniku operacji. W zmiennej rows znajduje się liczba wierszy, które uległy zmianie po wykonaniu naszej procedury.

Odczyt zwróconych danych

W momencie kiedy chcemy jednak odczytać wartości zwrócone przez zapytanie, musimy użyć innej metody i później odczytać jeszcze wyniki. Robimy to następująco:

// nie zapomnijmy dodać using na górze pliku funkcji
using System.Data.SqlClient;

// w ciele metody wystarczy użyć poniższego kodu:
var id = 4;
string eventName = "";
using (SqlConnection conn = new SqlConnection(config["DBConnection"]))
{
     conn.Open();

     var getNameCommand = $"SELECT Name, EventDate FROM [dbo].[Events] WHERE Id='{id}'";
     using (SqlCommand cmd = new SqlCommand(getNameCommand, conn))
     {
          var reader = await cmd.ExecuteReaderAsync();
          while (reader.Read())
          {
               eventName = String.Format("{0}", reader[0]);
          }
     }
}

W powyższym kodzie wykorzystałem zapytanie napisane w kodzie, żeby lepiej móc zobrazować co jest zwracane przez zapytanie I jak odczytujemy to z kodu. Gdy chcemy odczytać zwrócone dane z zapytania wykorzystać musimy metodę ExecuteReaderAsync(). Zwraca ona nam obiekt typu System.Data.SqlClient.SqlDataReader. W pętli while odczytujemy kolejne rekordy zwrócone przez baze danych. Metoda reader.Read() przechodzi do następnego rekordu (wiersza) wyniku zapytania I zwraca true, jeżeli kolejny wiersz istnieje. Odczytuję pierwsze pole (o indexie 0) z odczytywanego w tym momencie rekordu. Będzie to zatem pole o nazwie Name. I przypisuję jego wartość do zmiennej eventName. W mwmencie w którym chciałbym odczytać wartość pola EventDate musiałbym wyciągnąć drugi element z obiektu reader, czyli reader[1].

Jak widać odpytywanie SQLowej bazy danych z Azure Functions jest bardzo proste i przyjemne. Problemy mogą zacząć się w momencie w którym będziemy chcieli odczytywać złożone obiekty za pomocą tej biblioteki. Ja nie miałem jeszcze takiej potrzeby, ale może Ty miałeś? Jeśli tak to podziel się takim doświadczeniem w komentarzu.

Jan Antonin Kolar 🇨🇿


  1. oczywiście to żart 😉

Zostaw odpowiedź

Twój adres email nie zostanie upubliczniony.* Pola wymagane *

This site uses Akismet to reduce spam. Learn how your comment data is processed.