Асинхронная функциональность отсутствует в интерфейсе 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());
}