Utilisation de Dapper QueryAsync pour renvoyer un seul objet

asynchronous c# dapper repository

Question

Malheureusement, notre base de données date des années 90. Son héritage est tellement fort que nous utilisons toujours le SP pour effectuer la plupart des opérations du CRUD. Cependant, il semble que Dapper convient plutôt bien et nous venons juste de commencer à jouer avec.

Cependant, je suis un peu préoccupé par la façon de gérer une seule ligne de données. Dans ce cas, j'utilise QueryAsync pour appeler le fournisseur de services en transmettant un ID. Comme vous pouvez le voir, l'objet retourne en dehors de l'appel asynchrone (*).

Est-ce que je vais avoir des ennuis? Si oui, est-ce que quelqu'un sait comment le gérer? Dois-je utiliser un QuerySync à la place?

public class SchemePolicyRepository : ISchemePolicyRepository
{
    private readonly SqlConnection sql;

    protected SchemePolicyRepository(SqlConnection connection)
    {
        sql = connection;
    }
    ... 
    public async Task<SchemePolicy> GetById(string id)
    {
        var schemePolicy = await sql.QueryAsync<SchemePolicy>("risk.iE_GetSchemePolicyById",
            new { Id = id },
            commandType: CommandType.StoredProcedure);
        return schemePolicy != null ? schemePolicy.FirstOrDefault() : null;
    }
    ...
}

(*) L'objet SchemePolicy renvoyé par FirstOfDefault () n'est pas une méthode asynchrone.

Réponse acceptée

Tout d'abord, je ne pense pas que vous ayez besoin de la null check , Dapper retournera zéro ligne pour une requête. Prenez note que ceci est vrai pour SQL Server mais devrait être le même pour tous les autres SGBDR. Donc ça

return schemePolicy != null ? schemePolicy.FirstOrDefault() : null;

peut être simplement écrit comme

return schemePolicy.FirstOrDefault();

Maintenant, pour aborder le véritable problème, et vous avez mentionné:

l'objet retourne en dehors de l'appel asynchrone (*)

Ce n'est pas vrai. Si vous l'écrivez d'une manière ou d'une autre, vous obtiendrez UNIQUEMENT votre objet après l'exécution de la requête. Ainsi, deux ensembles de codes produiront le même comportement:

var schemePolicy = await sql.QueryAsync<SchemePolicy>("sp", {rest of code});
return schemePolicy.FirstOrDefault();

et

var schemePolicy = sql.QueryAsync<SchemePolicy>("sp", {rest of code});
return schemePolicy.Result.FirstOrDefault();

Le problème est vraiment maintenant avec la façon dont vous appelez GetById pour vous assurer que (1) la méthode ne bloquera aucun autre thread et (2) que vous obtiendrez votre objet cible UNIQUEMENT lorsque l'exécution de la requête est terminée. Voici un extrait pour une application de console que vous pouvez tester avec:

static async void GetValue()
{
    var repo = new SchemePolicyRepository(new DbManager()); // creates an open connection 
    var result = await repo.GetById();
    Console.WriteLine(result);
}

static void Main(string[] args)
{
    GetValue();   
    Console.WriteLine("Query is running...");
    Console.ReadKey();
}

Ce test vous montrera que GetValue qui par conséquent appelle la méthode GetById ne bloque pas le reste du code. En outre, rien n'est renvoyé par FirstOrDefault tant que la requête n'a pas été traitée.

Voici le code de prise en charge de la requête au cas où quelqu'un voudrait vérifier que le concept est valide (le code fonctionne avec SQL Server 2008 et versions ultérieures):

public async Task<int> GetById()
{
    var sql = @"
WAITFOR DELAY '00:00:05';
select 1 where 1=1";

    var result = await {the_open_connection}.QueryAsync<int>(sql);    
    return result.FirstOrDefault();
}


Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi