Асинхронная функциональность отсутствует в интерфейсе IDbCommand

Это разумный способ добавить асинхронную функциональность в интерфейс IDbCommand?

public async static Task<IDataReader> ExecuteReaderAsync(this IDbCommand self) {
    DbCommand dbCommand = self as DbCommand;
    if (dbCommand != null) {
        return await dbCommand.ExecuteReaderAsync().ContinueWith(task => (IDataReader)task.Result);
    } else {
        return await Task.Run(() => self.ExecuteReader());
    }
}

В частности, я не совсем уверен, каковы последствия использования "ContinueWith" для фальсификации ковариации "Task".

Кроме того, в маловероятном случае, когда входящий экземпляр "self" не наследуется от DbCommand, будет ли поток пула потоков использоваться и блокироваться во время выполнения "self.ExecuteReader()"?

Вот ссылка на мою полную реализацию расширений IDb для поддержки асинхронности.

Спасибо

2 ответа

Просто потому, что он чище, я бы воспользовался тем, что вы используете async а также await покончить с актерами в ContinueWith(), await оценивает объект типа TResult когда используется на Task<TResult>, Я собирался предложить синтаксис return (IDataReader)await dbCommand.ExecuteReaderAsync();, но потом я вспомнил, что компилятор уже знает, что DbDataReader является IDataReader, Протестировано в VS 2013 и VS 2015 Preview (не знаю, на что вы ориентируетесь, но я предполагаю, что все компиляторы C#, которые поддерживают await должен работать с этим):

public async static Task<IDataReader> ExecuteReaderAsync(this IDbCommand self) {
    DbCommand dbCommand = self as DbCommand;
    if (dbCommand != null) {
        return await dbCommand.ExecuteReaderAsync();
    } else {
        return await Task.Run(() => self.ExecuteReader());
    }
}

Теперь вы используете await к его полному потенциалу и сохранению нескольких байтов кода;-).

Самая большая проблема с этой реализацией - это, конечно, тестирование типов во время выполнения в self as DbCommand, По моему мнению, DbCommand следует использовать вместоIDbCommand, Это позволит вам удалить приведение во время выполнения. Однако вы, вероятно, не написали бы эту библиотеку, если бы не было проблем с переключением всего из IDbCommand в DbCommand и проверка типа во время выполнения, вероятно, достаточно производительная.

Синтаксис Visual Studio 2017

В более новых версиях C# вы можете использовать is ключевое слово вместо as написать более краткий код:

public async static Task<IDataReader> ExecuteReaderAsync(this IDbCommand self) {
    if (self is DbCommand dbCommand) {
        return await dbCommand.ExecuteReaderAsync();
    } else {
        return await Task.Run(() => self.ExecuteReader());
    }
}

Вы скучаете по async а также await если вы используете.NET 4.5. То, как вы пытаетесь сделать это правильно, и надеюсь, что вы обрабатываете соединения отдельно.

public static async Task<IDataReader> ExecuteReaderAsync(this IDbCommand self)
{
    var dbCommand = self as DbCommand;
    if (dbCommand != null)
    {
        return await dbCommand.ExecuteReaderAsync();
    }

    return await Task.Run(() => self.ExecuteReader());
}
Другие вопросы по тегам