2014-10-01 3 views
3

Является ли это разумным способом добавления асинхронных функций в интерфейс 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» подделать ковариация «задачи».

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

Вот a link к моей полной реализации расширений IDb для поддержки async.

Спасибо

+0

Вы собираетесь разместить свою библиотеку как пакет nuget? – binki

ответ

3

Вы пропускаете 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()); 
} 
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. Вероятно, вы бы не написали эту библиотеку, если не было проблем с переключением всего: от IDbCommand до DbCommand, и проверка типа времени выполнения, вероятно, достаточно высока.

Смежные вопросы