Вот настройка: у меня есть проект с открытым исходным кодом под названием 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, это сработает :) - вот изображение того, что я имею в виду: