Utiliser C# pour connecter et exécuter des commandes SQL sur Azure Cosmos DB for PostgreSQL

S’APPLIQUE À : Azure Cosmos DB for PostgreSQL (avec l’extension de base de données Citus pour PostgreSQL)

Ce guide de démarrage rapide vous montre comment utiliser du code C# pour vous connecter à un cluster et utiliser des instructions SQL pour créer une table. Ensuite, vous insérerez, interrogerez, mettrez à jour et supprimerez des données dans la base de données. Cet article suppose que vous connaissez les bases du développement C#, et que vous ne savez pas utiliser Azure Cosmos DB for PostgreSQL.

Installer la bibliothèque PostgreSQL

Les exemples de code de cet article nécessitent la bibliothèque Npgsql. Vous devez installer Npgsql avec votre gestionnaire de package de langage (par exemple, NuGet dans Visual Studio).)

Se connecter, créer une table et insérer des données

Nous allez nous connecter à un cluster et charger les données à l’aide d’instructions SQL CREATE TABLE et INSERT INTO. Le code utilise ces méthodes de classe NpgsqlCommand :

  • Open() pour établir une connexion à Azure Cosmos DB for PostgreSQL
  • CreateCommand() pour définir la propriété CommandText.
  • ExecuteNonQuery() pour exécuter les commandes de base de données

Conseil

L’exemple de code ci-dessous utilise un pool de connexions pour créer et gérer des connexions à PostgreSQL. Le regroupement de connexions côté application est fortement recommandé, car :

  • Elle garantit que l’application ne génère pas trop de connexions à la base de données, et évite ainsi de dépasser les limites de connexion.
  • Cela peut contribuer à améliorer considérablement les performances, à la fois la latence et le débit. Le processus serveur PostgreSQL doit être dupliqué pour gérer chaque nouvelle connexion et réutiliser une connexion, ce qui évite cette surcharge.

Dans le code suivant, remplacez <cluster> par le nom de votre cluster et <mot de passe> par votre mot de passe d’administration.

using System;
using Npgsql;
namespace Driver
{
    public class AzurePostgresCreate
    {
       
        static void Main(string[] args)
        {
            // Replace <cluster> with your cluster name and <password> with your password:
            var connStr = new NpgsqlConnectionStringBuilder("Server = c-<cluster>.<uniqueID>.postgres.cosmos.azure.com; Database = citus; Port = 5432; User Id = citus; Password = <password>; Ssl Mode = Require; Pooling = true; Minimum Pool Size=0; Maximum Pool Size =50 ");

            connStr.TrustServerCertificate = true;

            using (var conn = new NpgsqlConnection(connStr.ToString()))
            {
                Console.Out.WriteLine("Opening connection");
                conn.Open();
                using (var command = new NpgsqlCommand("DROP TABLE IF EXISTS pharmacy;", conn))
                {
                    command.ExecuteNonQuery();
                    Console.Out.WriteLine("Finished dropping table (if existed)");
                }
                using (var command = new NpgsqlCommand("CREATE TABLE pharmacy (pharmacy_id integer ,pharmacy_name text,city text,state text,zip_code integer);", conn))
                {
                    command.ExecuteNonQuery();
                    Console.Out.WriteLine("Finished creating table");
                }
                using (var command = new NpgsqlCommand("CREATE INDEX idx_pharmacy_id ON pharmacy(pharmacy_id);", conn))
                {
                    command.ExecuteNonQuery();
                    Console.Out.WriteLine("Finished creating index");
                }
                using (var command = new NpgsqlCommand("INSERT INTO  pharmacy  (pharmacy_id,pharmacy_name,city,state,zip_code) VALUES (@n1, @q1, @a, @b, @c)", conn))
                {
                    command.Parameters.AddWithValue("n1", 0);
                    command.Parameters.AddWithValue("q1", "Target");
                    command.Parameters.AddWithValue("a", "Sunnyvale");
                    command.Parameters.AddWithValue("b", "California");
                    command.Parameters.AddWithValue("c", 94001);
                    int nRows = command.ExecuteNonQuery();
                    Console.Out.WriteLine(String.Format("Number of rows inserted={0}", nRows));
                }

            }
            Console.WriteLine("Press RETURN to exit");
            Console.ReadLine();
        }
    }
}

Distribuer des tables

Azure Cosmos DB for PostgreSQL vous offre la super puissance de distribution de tables sur plusieurs nœuds à des fins de scalabilité. Utilisez le code suivant pour distribuer une table. Vous pouvez en savoir plus sur create_distributed_table et la colonne de distribution dans Colonne de distribution (également appelée clé de partition).

Notes

La distribution de tables leur permet de croître sur tous les nœuds Worker ajoutés au cluster.

Dans le code suivant, remplacez <cluster> par le nom de votre cluster et <mot de passe> par votre mot de passe d’administration.

using System;
using Npgsql;
namespace Driver
{
    public class AzurePostgresCreate
    {
      
        static void Main(string[] args)
        {
            // Replace <cluster> with your cluster name and <password> with your password:
            var connStr = new NpgsqlConnectionStringBuilder("Server = c-<cluster>.<uniqueID>.postgres.cosmos.azure.com; Database = citus; Port = 5432; User Id = citus; Password = {your password}; Ssl Mode = Require; Pooling = true; Minimum Pool Size=0; Maximum Pool Size =50");

            connStr.TrustServerCertificate = true;

            using (var conn = new NpgsqlConnection(connStr.ToString()))
            {
                Console.Out.WriteLine("Opening connection");
                conn.Open();
                using (var command = new NpgsqlCommand("select create_distributed_table('pharmacy','pharmacy_id');", conn))
                {
                    command.ExecuteNonQuery();
                    Console.Out.WriteLine("Finished distributing the table");
                }

            }
            Console.WriteLine("Press RETURN to exit");
            Console.ReadLine();
        }
    }
}

Lire les données

Utilisez le code suivant pour vous connecter et lire des données à l’aide d’une instruction SQL SELECT. Le code utilise ces méthodes de classe NpgsqlCommand :

  • Open() pour établir une connexion à Azure Cosmos DB for PostgreSQL.
  • Les méthodes CreateCommand() et ExecuteReader() pour exécuter les commandes de base de données.
  • La méthode Read() pour accéder à l’enregistrement dans les résultats.
  • Les méthodes GetInt32() et GetString() pour analyser les valeurs dans l’enregistrement.

Dans le code suivant, remplacez <cluster> par le nom de votre cluster et <mot de passe> par votre mot de passe d’administration.

using System;
using Npgsql;
namespace Driver
{
    public class read
    {

        static void Main(string[] args)
        {
            // Replace <cluster> with your cluster name and <password> with your password:
            var connStr = new NpgsqlConnectionStringBuilder("Server = c-<cluster>.<uniqueID>.postgres.cosmos.azure.com; Database = citus; Port = 5432; User Id = citus; Password = <password>; Ssl Mode = Require; Pooling = true; Minimum Pool Size=0; Maximum Pool Size =50 ");

            connStr.TrustServerCertificate = true;

            using (var conn = new NpgsqlConnection(connStr.ToString()))
            {
                Console.Out.WriteLine("Opening connection");
                conn.Open();
                using (var command = new NpgsqlCommand("SELECT * FROM pharmacy", conn))
                {
                    var reader = command.ExecuteReader();
                    while (reader.Read())
                    {
                        Console.WriteLine(
                            string.Format(
                                "Reading from table=({0}, {1}, {2}, {3}, {4})",
                                reader.GetInt32(0).ToString(),
                                reader.GetString(1),
                                 reader.GetString(2),
                                 reader.GetString(3),
                                reader.GetInt32(4).ToString()
                                )
                            );
                    }
                    reader.Close();
                }
            }
            Console.WriteLine("Press RETURN to exit");
            Console.ReadLine();
        }
    }
}

Mettre à jour des données

Utilisez le code suivant pour vous connecter et mettre à jour les données à l’aide d’une instruction SQL UPDATE. Dans le code, remplacez <cluster> par le nom de votre cluster et <mot de passe> par votre mot de passe d’administration.

using System;
using Npgsql;
namespace Driver
{
    public class AzurePostgresUpdate
    {
        static void Main(string[] args)
        {
            // Replace <cluster> with your cluster name and <password> with your password:
            var connStr = new NpgsqlConnectionStringBuilder("Server = c-<cluster>.<uniqueID>.postgres.cosmos.azure.com; Database = citus; Port = 5432; User Id = citus; Password = <password>; Ssl Mode = Require; Pooling = true; Minimum Pool Size=0; Maximum Pool Size =50 ");

            connStr.TrustServerCertificate = true;

            using (var conn = new NpgsqlConnection(connStr.ToString()))
            {
                Console.Out.WriteLine("Opening connection");
                conn.Open();
                using (var command = new NpgsqlCommand("UPDATE pharmacy SET city = @q WHERE pharmacy_id = @n", conn))
                {
                    command.Parameters.AddWithValue("n", 0);
                    command.Parameters.AddWithValue("q", "guntur");
                    int nRows = command.ExecuteNonQuery();
                    Console.Out.WriteLine(String.Format("Number of rows updated={0}", nRows));
                }
            }
            Console.WriteLine("Press RETURN to exit");
            Console.ReadLine();
        }
    }
}

Suppression de données

Utilisez le code suivant pour vous connecter et supprimer les données à l’aide d’une instruction SQL DELETE. Dans le code, remplacez <cluster> par le nom de votre cluster et <mot de passe> par votre mot de passe d’administration.

using System;
using Npgsql;
namespace Driver
{
    public class AzurePostgresDelete
    {
       
        static void Main(string[] args)
        {
            // Replace <cluster> with your cluster name and <password> with your password:
            var connStr = new NpgsqlConnectionStringBuilder("Server = c-<cluster>.<uniqueID>.postgres.cosmos.azure.com; Database = citus; Port = 5432; User Id = citus; Password = {your password}; Ssl Mode = Require; Pooling = true; Minimum Pool Size=0; Maximum Pool Size =50 ");

            connStr.TrustServerCertificate = true;

            using (var conn = new NpgsqlConnection(connStr.ToString()))
            {

                Console.Out.WriteLine("Opening connection");
                conn.Open();
                using (var command = new NpgsqlCommand("DELETE FROM pharmacy WHERE pharmacy_id = @n", conn))
                {
                    command.Parameters.AddWithValue("n", 0);
                    int nRows = command.ExecuteNonQuery();
                    Console.Out.WriteLine(String.Format("Number of rows deleted={0}", nRows));
                }
            }
            Console.WriteLine("Press RETURN to exit");
            Console.ReadLine();
        }
    }
}

Commande COPY pour l’ingestion rapide

La commande COPY peut générer un débit considérable lors de l’ingestion de données dans Azure Cosmos DB for PostgreSQL. La commande COPY peut ingérer des données dans des fichiers ou à partir de micro-lots de données en mémoire pour l’ingestion en temps réel.

Commande COPY pour charger des données à partir d’un fichier

L’exemple de code suivant copie des données à partir d’un fichier CSV dans une table de base de données.

L’exemple de code nécessite que le fichier pharmacies.csv se trouve dans votre dossier Documents. Dans le code, remplacez <cluster> par le nom de votre cluster et <mot de passe> par votre mot de passe d’administration.

using Npgsql;
public class csvtotable
{

    static void Main(string[] args)
    {
        String sDestinationSchemaAndTableName = "pharmacy";
        String sFromFilePath = "C:\\Users\\Documents\\pharmacies.csv";
       
        // Replace <cluster> with your cluster name and <password> with your password:
        var connStr = new NpgsqlConnectionStringBuilder("Server = c-<cluster>.<uniqueID>.postgres.cosmos.azure.com; Database = citus; Port = 5432; User Id = citus; Password = <password>; Ssl Mode = Require; Pooling = true; Minimum Pool Size=0; Maximum Pool Size =50 ");
            
        connStr.TrustServerCertificate = true;

        NpgsqlConnection conn = new NpgsqlConnection(connStr.ToString());
        NpgsqlCommand cmd = new NpgsqlCommand();

        conn.Open();

        if (File.Exists(sFromFilePath))
        {
            using (var writer = conn.BeginTextImport("COPY " + sDestinationSchemaAndTableName + " FROM STDIN WITH(FORMAT CSV, HEADER true,NULL ''); "))
            {
                foreach (String sLine in File.ReadAllLines(sFromFilePath))
                {
                    writer.WriteLine(sLine);
                }
            }
            Console.WriteLine("csv file data copied sucessfully");
        }
    }
}

Commande COPY pour charger des données en mémoire

L’exemple de code suivant copie des données en mémoire dans une table. Dans le code, remplacez <cluster> par le nom de votre cluster et <mot de passe> par votre mot de passe d’administration.

using Npgsql;
using NpgsqlTypes;
namespace Driver
{
    public class InMemory
    {

        static async Task Main(string[] args)
        {
         
             // Replace <cluster> with your cluster name and <password> with your password:
            var connStr = new NpgsqlConnectionStringBuilder("Server = c-<cluster>.<uniqueID>.postgres.cosmos.azure.com; Database = citus; Port = 5432; User Id = citus; Password = <password>; Ssl Mode = Require; Pooling = true; Minimum Pool Size=0; Maximum Pool Size =50 ");

            connStr.TrustServerCertificate = true;

            using (var conn = new NpgsqlConnection(connStr.ToString()))
            {
                conn.Open();
                var text = new dynamic[] { 0, "Target", "Sunnyvale", "California", 94001 };
                using (var writer = conn.BeginBinaryImport("COPY pharmacy  FROM STDIN (FORMAT BINARY)"))
                {
                    writer.StartRow();
                    foreach (var item in text)
                    {
                        writer.Write(item);
                    }
                    writer.Complete();
                }
                Console.WriteLine("in-memory data copied sucessfully");
            }
        }
    }
}

Nouvelle tentative d’application pour les échecs de requête de base de données

Il arrive parfois que les requêtes de base de données en provenance de votre application échouent. Ces problèmes peuvent se produire dans différents scénarios, comme une défaillance réseau entre une application et une base de données, un mot de passe incorrect, etc. Certains problèmes peuvent être temporaires et se résoudre d’eux-mêmes en quelques secondes ou quelques minutes. Vous pouvez configurer la logique de nouvelle tentative dans votre application pour surmonter les erreurs temporaires.

La configuration de la logique de nouvelle tentative dans votre application permet d’améliorer l’expérience de l’utilisateur final. Dans les scénarios de défaillance, les utilisateurs attendent simplement un peu plus longtemps que l’application traite les requêtes, au lieu d’être confrontés à des erreurs.

L’exemple ci-dessous montre comment implémenter une logique de nouvelle tentative dans votre application. L’exemple d’extrait de code tente une requête de base de données toutes les 60 secondes (jusqu’à cinq fois) jusqu’à ce qu’elle réussisse. Le nombre et la fréquence des nouvelles tentatives peuvent être configurés en fonction des besoins de votre application.

Dans ce code, remplacez <cluster> par le nom de votre cluster et <mot de passe> par votre mot de passe d’administration.

using System;
using System.Data;
using System.Runtime.InteropServices;
using System.Text;
using Npgsql;

namespace Driver
{
    public class Reconnect
    {
        
        // Replace <cluster> with your cluster name and <password> with your password:
        static string connStr = new NpgsqlConnectionStringBuilder("Server = c-<cluster>.<uniqueID>.postgres.cosmos.azure.com; Database = citus; Port = 5432; User Id = citus; Password = <password>; Ssl Mode = Require; Pooling = true; Minimum Pool Size=0; Maximum Pool Size =50;TrustServerCertificate = true").ToString();
        static string executeRetry(string sql, int retryCount)
        {
            for (int i = 0; i < retryCount; i++)
            {
                try
                {
                    using (var conn = new NpgsqlConnection(connStr))
                    {
                        conn.Open();
                        DataTable dt = new DataTable();
                        using (var _cmd = new NpgsqlCommand(sql, conn))
                        {
                            NpgsqlDataAdapter _dap = new NpgsqlDataAdapter(_cmd);
                            _dap.Fill(dt);
                            conn.Close();
                            if (dt != null)
                            {
                                if (dt.Rows.Count > 0)
                                {
                                    int J = dt.Rows.Count;
                                    StringBuilder sb = new StringBuilder();

                                    for (int k = 0; k < dt.Rows.Count; k++)
                                    {
                                        for (int j = 0; j < dt.Columns.Count; j++)
                                        {
                                            sb.Append(dt.Rows[k][j] + ",");
                                        }
                                        sb.Remove(sb.Length - 1, 1);
                                        sb.Append("\n");
                                    }
                                    return sb.ToString();
                                }
                            }
                        }
                    }
                    return null;
                }
                catch (Exception e)
                {
                    Thread.Sleep(60000);
                    Console.WriteLine(e.Message);
                }
            }
            return null;
        }
        static void Main(string[] args)
        {
            string result = executeRetry("select 1",5);
            Console.WriteLine(result);
        }
    }
}

Étapes suivantes