Мне любопытно узнать, столкнулся ли кто-то еще с этой проблемой...
Я использую Dapper как на ORM для проекта и создавал некоторые из моих собственных методов расширения вне интерфейса IDbConnection
, чтобы упростить код, где я столкнулся (что я обнаружил), запутывая ошибку.
Я пройду процесс, через который я прошел.
Сначала я добавил метод расширения для моего проекта в статическом классе с именем DbExtensions
следующим образом:
using System.Collections.Generic;
using System.Data;
using System.Linq;
public static class DbExtensions
{
public static T Scalar<T>(
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
{
var ret = cnn.Query<T>(sql, param as object, transaction, buffered, commandTimeout, commandType).First();
return ret;
}
}
Это создает ошибку компиляции со следующим описанием:
'System.Data.IDbConnection' has no applicable method named 'Query' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.
Это хорошо, и ошибка на самом деле весьма полезна, поскольку она даже подсказывает, как ее исправить. Поэтому я затем пытаюсь:
using System.Collections.Generic;
using System.Data;
using System.Linq;
public static class DbExtensions
{
public static T Scalar<T>(
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
{
var ret = SqlMapper.Query<T>(cnn, sql, param, transaction, buffered, commandTimeout, commandType).First();
return ret;
}
}
и он правильно компилируется. Что-то странное происходит. В Visual Studio, если я принимаю возвращаемое значение SqlMapper.Query<T>
, которое должно быть IEnumerable<T>
, и я пытаюсь работать с ним, Visual Studio не дает мне никаких свойств intellisense, кроме тех, которые унаследованы через object
.
Думаю, что я просто делаю то, что intellisense недостаточно умен, чтобы понять, я продолжаю свой веселый путь... пока я на самом деле не попытаюсь запустить код.
Когда я пытаюсь запустить его, он запускается там, где я вызываю .First()
со следующей ошибкой:
'System.Collections.Generic.List<MyNameSpace.MyClass>' does not contain a definition for 'First'
Теперь эта ошибка, я подумал, было интересно... После того, как я на мгновение ударился головой, я понял, что первый аргумент жаловался на динамическую типизацию...
Я предполагаю, что эта ошибка возникает, потому что компилятор не может создать общий шаблон, потому что он не знает, что Query возвращает IEnumerable<T>
, поскольку он выполняется в DLR? Я хотел бы услышать, как кто-то объяснил это, кто был осведомлен. Я по существу нашел два способа исправить это:
- Введите параметр
dynamic
вobject
- Передача возвращаемого значения в
IEnumerable<T>
using System.Collections.Generic;
using System.Data;
using System.Linq;
public static class DbExtensions
{
public static T Scalar<T>(
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
{
var ret = SqlMapper.Query<T>(cnn, sql, param as object, transaction, buffered, commandTimeout, commandType).First();
return ret;
}
}
using System.Collections.Generic;
using System.Data;
using System.Linq;
public static class DbExtensions
{
public static T Scalar2<T>(
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
{
var ret = ((IEnumerable<T>)SqlMapper.Query<T>(cnn, sql, param, transaction, commandTimeout, commandType)).First();
return ret;
}
}
В РЕЗЮМЕ:
Я новичок в работе с qwerks DLR, и, похоже, есть некоторые предостережения, которые следует учитывать при запуске с динамическими + Generics...?
Я знаю, что это не вопрос, но когда я начал писать это, я не знал, что происходит, и я понял это в этом процессе! Я думал, что это может помочь кому-то еще с подобными проблемами, хотя...