Может ли управляемый драйвер Oracle правильно использовать асинхронное ожидание?

Я пытался сделать запрос Oracle с помощью функции асинхронного / ожидания.NET. Результирующий набор довольно большой и занимает около 5-10 секунд, чтобы вернуться. Window_Loaded вешает поток пользовательского интерфейса, по сути, я хотел использовать async / wait, чтобы выполнить запрос в фоновом режиме, а затем обновить отображение данных с результатом.

Так это проблема с драйвером Oracle или ошибка кода? Например, что-то здесь делается синхронно, а не асинхронно? Я использую последние Oracle.ManagedDataAccess Я мог бы получить с веб-сайта Oracle.

async Task<DataTable> AccessOracleAsync()
{
    DataTable dt;
    using(OracleConnection conn = new OracleConnection(ConfigurationManager.ConnectionStrings["connStr"].ConnectionString))
    using (OracleCommand cmd = new OracleCommand(@"SELECT * FROM myTbl", conn))
    {
        await conn.OpenAsync();
        using (var reader = await cmd.ExecuteReaderAsync())
        {
            dt = new DataTable();
            dt.Load(reader);                        
        }
    }

    return dt;
}

private async void Window_Loaded(object sender, RoutedEventArgs e)
{
    await AccessOracleAsync();
}

Я попробовал это, и он все еще блокирует интерфейс:

async Task<DataView> AccessOracleAsync()
{
        DataTable dt;
        using (OracleConnection conn = new OracleConnection(ConfigurationManager.ConnectionStrings["connStr"].ConnectionString))
        using (OracleCommand cmd = new OracleCommand(@"SELECT * FROM myTbl", conn))
        {
            await conn.OpenAsync().ConfigureAwait(false);
            using (DbDataReader reader = await cmd.ExecuteReaderAsync().ConfigureAwait(false))
            {
                dt = new DataTable();
                await Task.Run(() => dt.Load(reader)).ConfigureAwait(false);
            }

        }
        return dt.AsDataView();
}

private async void Window_Loaded(object sender, RoutedEventArgs e)
{
    Data1.ItemsSource = await AccessOracleAsync();
}

В итоге я изменил метод на что-то вроде этого, чтобы он не зашел в тупик. Похоже, у меня была правильная идея, просто, что библиотека Oracle Managed реализовала методы Async синхронно (только для соответствия интерфейсу).

private async Task<DataView> AccessOracleAsync()
{
        DataTable dt = new DataTable();
        using (OracleConnection conn = new OracleConnection(ConfigurationManager.ConnectionStrings["connStr"].ConnectionString))
        using (OracleCommand cmd = new OracleCommand(@"SELECT * myTbl", conn))
        {
            await Task.Run(() =>
                {
                    conn.Open();
                    using (DbDataReader reader = cmd.ExecuteReader())
                    {
                        dt.Load(reader);
                    }
                }).ConfigureAwait(false);

        }
        return dt.AsDataView();
}

4 ответа

Решение

Нет. Управляемый драйвер не поддерживает async / await,

Вы можете вызывать эти методы, поскольку они должны быть реализованы в соответствии с определением интерфейса, но код на самом деле является синхронным. Ты можешь использовать Task.Run если вы хотите, но вы не можете иметь два вызова одновременно (Oracle будет угрожать им синхронно).

(Я оставляю это как ответ, так как это, кажется, "решение" для того, чтобы заставить управляемый драйвер Oracle должным образом поддерживать асинхронность.)

Я нашел старую ветку (с 2010 года) на сайте Oracle, где премьер-министры Oracle говорят, что не поддерживают ее. Вы можете проголосовать (должен иметь учетную запись Oracle), чтобы включить эту функцию. Через 5 лет он, к сожалению, набрал только 60 голосов.

Спустя более 10 лет Oracle наконец выпустила версию управляемого драйвера для разработчиков (бета-версию) с поддержкой async/await.

Проблема с Github:
https://github.com/oracle/dotnet-db-samples/issues/144#issuecomment-1656674986

Инструкции Oracle:
https://docs.oracle.com/en/database/oracle/oracle-database/23/odpnt/featAsyncPipelining.html#GUID-27CA3823-92BA-489A-9356-9EAA7B86A4FE

Пакет Nuget для .NET Core:
https://www.nuget.org/packages/Oracle.ManagedDataAccess.Core/23.2.0-dev.

Вам необходимо включить предварительную версию в Visual Studio, если вы хотите установить ее, поскольку она находится только в разработке (бета-версия).

Существует проблема Github , которая установила веху в выпуске 23C для ODP.NET. Также было объявлено о демонстрации асинхронной реализации во время Oracle Cloud World 2022.

Другие вопросы по тегам