À l'aide de async / await avec DataReader ? ( sans moyen de tampons!)

Mon but est simple , je veux faire des e/S Asynchrones appels (à l'aide de async attendent) - mais :

Ok.

Actuellement voici mon code c'est du boulot, c'est de lire à partir de db et le projet de chaque ligne à un Func<>

public IEnumerable < T > GetSomeData < T > (string sql, Func < IDataRecord, T > projector)
{
    using(SqlConnection _conn = new SqlConnection(@"Data Source=..."))
    {
        using(SqlCommand _cmd = new SqlCommand(sql, _conn))
        {
            _conn.Open();
            _cmd.CommandTimeout = 100000;
            using(IDataReader rdr = _cmd.ExecuteReader())
            {
                while (rdr.Read())  yield    return projector(rdr);
            }
        }
    }
}

Alors , qu'est-projecteur ?

Chaque classe a une fonction qui reçoit un record ( IDataRecord) et de créer une entité :

Exemple :

public class MyClass
{
    public static MyClass MyClassFactory(IDataRecord record)
    {
        return new MyClass
        {
            Name = record["Name"].ToString(),
            Datee = DateTime.Parse(record["Datee"].ToString()),
            val = decimal.Parse(record["val"].ToString())
        };
    }
    public string Name    {   get;   set;  }
    public DateTime Datee    {  get;     set;  }
    public decimal val    {  get;    set;    }
}

Donc, ici , MyClassFactory serait le Func

Alors, comment je fonctionne actuellement ?

 var sql = @"SELECT TOP 1000 [NAME],[datee] ,[val]  FROM [WebERP].[dbo].[t]";
 var a = GetSomeData < MyClass > (sql, MyClass.MyClassFactory).Where(...); //notice the Func

Tous ok.

Le problème commence maintenant :

Ajoutant async à la méthode donne une erreur : ( Oui, je sais que Ienumerable est un Synchrone interface d'où le problème)

public async Task<IEnumerable < T >> GetSomeData < T > (string sql, Func < IDataRecord, T > projector)

ne peut pas être un itérateur bloc parce que
'Système.Le filetage.Les tâches.Tâche>'
n'est pas un itérateur type d'interface

Mais ce gars là n'a - :

À l'aide de async /await avec DataReader ? ( sans moyen de tampons!)

Qui NE compiler.

Question

Comment puis-je convertir mon code à soutenir pleinement asynchronse IO appel ?

(selon les conditions : sans des Flux de données, de dépendance , d'envoyer le projecteur en fonction comme argument , aucun moyen de tampons)

Pour de tels cas, il serait bien si C# soutenu IAsyncEnumerator. Si vous êtes OK avec le retour d'un rendez-vous rempli de liste dans un async façon dont la question devient beaucoup plus facile.
ToArray permet de créer un milieu tampon.
Votre code d'itérations. Le code qui ne compile pas. IEnumerable n'est pas le problème. L'itération (c'est à dire: yield return) est le problème. Quel est le problème avec un tampon?
Que diriez - asyncenum.codeplex.com
vous avez de l'exposer à l'appelant par l'élément de l'asynchronicité. IEnumerable ne peut pas le faire. En prenant un élément est toujours synchrone. Vous avez besoin d'utiliser un modèle asynchrone comme IAsyncEnumerator. Il semble raisonnable de bibliothèques autour de cette idée (asyncenum.codeplex.com). Rien de construit. Aussi, l'impact sur les performances prises pour la mise en mémoire tampon est si peu par rapport à tous les ADO.NET et SQL travail en évitant de mise en mémoire tampon ne pas avoir un effet significatif du débit. Aurait encore un sens pour la diffusion d'énormes ensembles de données.

OriginalL'auteur Royi Namir | 2014-05-25