U bevindt zich nu op een technische pagina over de software Mercator. Deze pagina bevat specifieke informatie die bestemd is voor professionals van de software Mercator. Wenst u naar algemenere informatie over Mercator door te gaan?


   Deze vraag niet meer stellen

Asynchrone toegang tot de SQL database met de Mercator API

0000003158     -      17-04-2023

Mercator heeft altijd een API gehad voor eenvoudige toegang tot zijn SQL database:

  • MercatorSqlConnection : verbinden met de database,
  • Zselect, Zselect<T> en ZselectDirect : gegevens te verkrijgen,
  • SqlExec : een SQL script uitvoeren,
  • BulkDataTable : uploaden naar SQL server via bulk DataTable.

Al deze klassen en methoden werken synchroon. Dit betekent dat tijdens de communicatie met de SQL server, de Mercator basis thread wordt geblokkeerd. Voor de gebruiker betekent dit dat de interface "bevroren" lijkt. Dit kan een bron van ongemak zijn als de gebruiker lang moet wachten.

Deze methoden bestaan in de Mercator API in asynchrone modus. Het zijn dus awaitables, wat hen toelaat om verder te gaan terwijl de gebruiker de controle over de basisthread terugneemt. Met andere woorden, de gebruiker kan doorgaan met andere dingen in Mercator, zoals het klikken op een knop "Annuleren" die het proces onderbreekt. Het wordt ook aanbevolen om deze methoden te gebruiken in asynchrone omgevingen zoals ASP.net core.

De Mercator API voorziet een uitbreiding (te vinden in MercatorExtensions van MercatorTunnel.dll) op System.Data.SqlClient.SqlConnection om een asynchrone verbinding mogelijk te maken.

Zoom
using (SqlConnection conn = new SqlConnection())
{
    var t = await conn.ConnectToMercatorAsync(MercatorUi.Globals.RepData);
    if (!t.Result)
    {
         MercatorUi.Dialogs.Stop(t.Error);
        return;
    }
    ...
}

 

Deze asynchrone methoden bestaan in de Mercator API:

  • ZselectAsyncZselectAsync<T> en ZselectDirectAsync : gegevens te verkrijgen,
  • SqlExecAsync : een SQL script uitvoeren,
  • BulkDataTableAsync : uploaden naar SQL server via bulk DataTable.

In tegenstelling tot hun synchrone tegenhangers tonen deze methoden geen dialoogvenster bij fouten. Ook is hun resultaat altijd een klasse met deze eigenschappen

  • Error : eventuele fouttekenreeks
  • Result : het resultaat indien geen fout (DataSet voor een SqlExecAsync, bijvoorbeeld)

Deze klasse bevat ook een methode Zstoperror die het gebruikelijke dialoogvenster weergeeft in geval van een fout.

Voorbeeld van gebruik :

Zoom
RetZselectAsync retZselectAsync = await Api.ZselectAsync(MercatorUi.Globals.RepData, reqSql);
if (retZselectAsync.Result == null)
{
    retZselectAsync.Zstoperror();
    return;
}
DataSet dataSet = retZselectAsync.Result;
...

 

Deze methoden accepteren ook een parameter CancellationTokenSource waarmee een verzoek kan worden gedaan om het huidige proces te onderbreken. Dit verzoek wordt gedaan via :

Zoom
cancellationTokenSource.Cancel();

Opmerking : CancellationTokenSource is IDisposable. Het wordt aanbevolen het te gebruiken in een using block.


In veel gevallen is het wenselijk om de basisthread niet te blokkeren, maar ook om de gebruiker niets anders te laten doen dan het proces dat zojuist is getriggerd te onderbreken. Asynchrone werking kan namelijk soms onverwacht gedrag opleveren als de geïmplementeerde code al deze situaties niet correct afhandelt. (Bijvoorbeeld, het scherm dat de door ZselectAsync verkregen resultaten zou moeten ontvangen, bestaat niet meer omdat de gebruiker het heeft gesloten).

Om dit te vergemakkelijken voorziet Mercator deze klasse :

MercatorUi._BaseClasses.ExclusiveBackgroundWorkerAsync

Zijn constructor ontvangt deze parameters:

  • actionAsync : van het type Func<Task>, die de uit te voeren asynchrone actie bevat
  • formWhereToCenterLoadingCircle : venster dat zal worden gebruikt als markering voor het centreren van een loadingCircle. Deze parameter is optioneel. Als hij niet is gedefinieerd, wordt de centrering uitgevoerd op het Mercator-venster.
  • cancellationTokenSource : Deze parameter is optioneel. Als hij wordt doorgegeven, komt er een "Annuleer"-knop onder de laadcirkel. Hiermee kan de gebruiker het proces afbreken.

Hieronder volgt een voorbeeld van uitvoering:

Zoom
using (System.Threading.CancellationTokenSource cancellationTokenSource = new System.Threading.CancellationTokenSource())
{
    RetZselectAsync r = null;
    MercatorUi._BaseClasses.ExclusiveBackgroundWorkerAsync ebwa = new MercatorUi._BaseClasses.ExclusiveBackgroundWorkerAsync(
                async () => r = await Api.ZselectAsync(Globals.RepData, reqSql, cancellationTokenSource: cancellationTokenSource),
                sigForm,
                cancellationTokenSource: cancellationTokenSource);
    if (cancellationTokenSource.IsCancellationRequested)
    {
        // de gebruiker heeft op Annuleren geklikt
        return;
    }
    else if (r == null)
    {
        // er is een uitzondering opgetreden in de code van deAsync actie
        Dialogs.Stop(ebwa.ExceptionDuringDoWork?.Message ?? "Unknown error!");
        return;
    }
    else if (r.Result == null)
    {
        // er is een SQL-fout opgetreden
        r.Zstoperror();
        return;
    }
    else
    {
        // alles is goed!
        DataSet dataSet = r.Result;
    }
}

 

Opmerking : Dit voorbeeld kan worden gebruikt voor andere asynchrone bewerkingen dan databasetoegang. Bijvoorbeeld voor het gebruik van een webservice.