Что вызывает "методы расширения не могут быть динамически отправлены" здесь?

Ошибка компиляции

"System.Data.SqlClient.SqlConnection" не имеет применимого метода с именем "Query", но, похоже, имеет метод расширения с этим именем. Методы расширения не могут быть динамически отправлены. Попробуйте привести динамические аргументы или вызвать метод расширения без синтаксиса метода расширения.

Теперь я знаю, как обойти проблему, но я пытаюсь лучше понять саму ошибку. У меня есть класс, который я строю, чтобы использовать Dapper. В конце я собираюсь предоставить больше пользовательских функций, чтобы сделать наш тип доступа к данным намного более упорядоченным. В частности, строительство в отслеживании и прочее. Тем не менее, прямо сейчас это так просто:

public class Connection : IDisposable
{
    private SqlConnection _connection;

    public Connection()
    {
        var connectionString = Convert.ToString(ConfigurationManager.ConnectionStrings["ConnectionString"]);
        _connection = new SqlConnection(connectionString);
        _connection.Open();
    }

    public void Dispose()
    {
        _connection.Close();
        _connection.Dispose();
    }

    public IEnumerable<dynamic> Query(string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
    {
        // this one works fine, without compile error, so I understand how to
        // workaround the error
        return Dapper.SqlMapper.Query(_connection, sql, param, transaction, buffered, commandTimeout, commandType);
    }

    public IEnumerable<T> Query<T>(string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
    {
        // this one is failing with the error
        return (IEnumerable<T>)_connection.Query(sql, param, transaction, buffered, commandTimeout, commandType);
    }
}

но достаточно интересно, если бы я просто выпустил заявление вроде этого:

_connection.Query("SELECT * FROM SomeTable");

он компилируется просто отлично.

Итак, кто-нибудь может помочь мне понять, почему использование такой же перегрузки внутри этих других методов не удается с этой ошибкой?

2 ответа

Решение

Итак, кто-нибудь может помочь мне понять, почему использование такой же перегрузки внутри этих других методов не удается с этой ошибкой?

Именно потому, что вы используете динамическое значение (param) в качестве одного из аргументов. Это означает, что он будет использовать динамическую диспетчеризацию... но динамическая диспетчеризация не поддерживается для методов расширения.

Решение простое: просто вызовите статический метод напрямую:

return SqlMapper.Query(_connection, sql, param, transaction,
                       buffered, commandTimeout, commandType);

(Это при условии, что вам действительно нужно param быть типом dynamic, конечно... как отмечено в комментариях, вы вполне можете просто изменить его на object.)

Другим решением той же проблемы является применение приведения типов к динамическому значению.

Я столкнулся с той же ошибкой компиляции с:

Url.Asset( "path/" + article.logo );

Что было решено путем:

Url.Asset( "path/" + (string) article.logo );

Примечание: в этом случае известно, что динамическое значение является строкой; факт, подкрепленный существующей конкатенацией строк.

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