Вот настройка: у меня есть проект с открытым исходным кодом под названием Massive, и я использую динамику как способ создания SQL на лету и динамические наборы результатов на лету.
Для завершения базы данных я использую System.Data.Common и материал ProviderFactory. Вот пример, который отлично работает (он статический, поэтому вы можете запустить его в консоли):
static DbCommand CreateCommand(string sql) {
return DbProviderFactories.GetFactory("System.Data.SqlClient")
.CreateCommand();
}
static DbConnection OpenConnection() {
return DbProviderFactories.GetFactory("System.Data.SqlClient")
.CreateConnection();
}
public static dynamic DynamicWeirdness() {
using (var conn = OpenConnection()) {
var cmd = CreateCommand("SELECT * FROM Products");
cmd.Connection = conn;
}
Console.WriteLine("It worked!");
Console.Read();
return null;
}
Результат выполнения этого кода: "Это сработало!"
Теперь, если я изменю строковый аргумент на динамический - в частности, ExpandoObject (сделайте вид, что где-то есть подпрограмма, которая превращает Expando в SQL) - выдается странная ошибка. Вот код:
То, что работало до сих пор, терпит неудачу с сообщением, которое не имеет смысла. SqlConnection - это DbConnection - более того, если вы наведете указатель мыши на код при отладке, вы увидите, что все типы являются типами SQL. "conn" - это SqlConnection, "cmd" - это SqlCommand.
Эта ошибка не имеет абсолютно никакого смысла, но, что более важно, она вызвана наличием ExpandoObject, который не касается какого-либо кода реализации. Различия между двумя процедурами: 1 - я изменил аргумент в CreateCommand(), чтобы принимать "динамический" вместо строки 2 - Я создал ExpandoObject и установил свойство.
Это становится страннее.
Если просто использовать строку вместо ExpandoObject - все работает отлично!
//THIS WORKS
static DbCommand CreateCommand(dynamic item) {
return DbProviderFactories.GetFactory("System.Data.SqlClient").CreateCommand();
}
static DbConnection OpenConnection() {
return DbProviderFactories.GetFactory("System.Data.SqlClient").CreateConnection();
}
public static dynamic DynamicWeirdness() {
dynamic ex = new ExpandoObject();
ex.TableName = "Products";
using (var conn = OpenConnection()) {
//use a string instead of the Expando
var cmd = CreateCommand("HI THERE");
cmd.Connection = conn;
}
Console.WriteLine("It worked!");
Console.Read();
return null;
}
Если я поменяю аргумент для CreateCommand() на мой ExpandoObject ("ex") - это заставит весь код быть "динамическим выражением", которое вычисляется во время выполнения.
Похоже, что оценка во время выполнения этого кода отличается от оценки во время компиляции... что не имеет смысла.
** ОБНОВЛЕНИЕ: я должен добавить здесь, что если я жестко закодирую все, чтобы явно использовать SqlConnection и SqlCommand, это работает :) - вот изображение того, что я имею в виду: