Как использовать SqlBulkCopy для написания IAsyncEnumerable - PullRequest
1 голос
/ 31 января 2020

У меня есть следующий метод, который возвращает IAsyncEnumerable<T>:

async IAsyncEnumerable<T> RunReport()
{
    var handler = new HttpClientHandler();

    var client = new HttpClient(handler);
    client.BaseAddress = new Uri("");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var settings = new JsonSerializerSettings();

    var jsonFormatter = new JsonMediaTypeFormatter() { SerializerSettings = settings };

    var requestMessage = new HttpRequestMessage(HttpMethod.Get, "api/controler");
    var response = await client.SendAsync(requestMessage);

    response.EnsureSuccessStatusCode();

    using (var stream = await response.Content.ReadAsStreamAsync())
    {
        using (var reader = new StreamReader(stream))
        {
            while (!reader.EndOfStream)
            {
                var linesJson = await reader.ReadLineAsync();
                var line = JsonConvert.DeserializeObject<List<T>>(linesJson, jsonFormatter.SerializerSettings);

                foreach (var line in lines)
                    yield return line;
            }
        }
    }
}

Я хотел бы передать этот поток результатов в базу данных, используя метод SqlBulkCopy WriteToServerAsync, но не могу выясните, как превратить его в IDataReader или любой другой тип в списке перегрузки WriteToServerAsync.

Я открыт для использования чего-то другого, кроме массового копирования, при условии, что оно достаточно эффективно.

1 Ответ

0 голосов
/ 31 января 2020

, используя пример здесь , я пришел к IDataReader, который принимает IAsyncEnumerable и реализует соответствующую часть интерфейса.

public class GenericDataReader<T> : IDataReader where T : class
{
    private readonly IAsyncEnumerator<T> _asychEnumerator;
    private readonly List<FieldInfo> _fields = new List<FieldInfo>();

    public GenericDataReader(IAsyncEnumerable<T> asyncEnumerable)
    {
        _asychEnumerator = asyncEnumerable.GetAsyncEnumerator();

        foreach (FieldInfo fieldinfo in typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public))
        {
            _fields.Add(fieldinfo);
        }
    }

    public int FieldCount => _fields.Count;

    public void Dispose() { Close(); }

    public bool Read()
    {
        return _asycEnumerator.MoveNextAsync().Result;
    }

    public async void Close(){ await _asychEnumerator.DisposeAsync(); }

    public Type GetFieldType(int i){ return _fields[i].FieldType; }

    public string GetName(int i) { return _fields[i].Name; }

    public object GetValue(int i){ return _fields[i].GetValue(_asychEnumerator.Current); }
}   

Я все еще работаю через пример, но я немного опасаюсь реализации метода Read ().

...