Why is an ExpandoObject breaking code that otherwise works just fine?

前端 未结 7 948
感动是毒
感动是毒 2021-02-01 02:12

Here\'s the setup: I have an Open Source project called Massive and I\'m slinging around dynamics as a way of creating SQL on the fly, and dynamic result sets on the fly.

<
7条回答
  •  说谎
    说谎 (楼主)
    2021-02-01 02:38

    Because you're using dynamic as the argument to CreateCommand(), the cmd variable is also dynamic, which means its type is resolved at runtime to be SqlCommand. By contrast, the conn variable is not dynamic and is compiled to be of type DbConnection.

    Basically, SqlCommand.Connection is of type SqlConnection, so the conn variable, which is of type DbConnection, is an invalid value to set Connection to. You can fix this by either casting conn to an SqlConnection, or making the conn variable dynamic.

    The reason it worked fine before was because cmd was actually a DbCommand variable (even so it pointed to the same object), and the DbCommand.Connection property is of type DbConnection. i.e. the SqlCommand class has a new definition of the Connection property.

    Source issues annotated:

     public static dynamic DynamicWeirdness() {
        dynamic ex = new ExpandoObject();
        ex.TableName = "Products";
        using (var conn = OpenConnection()) { //'conn' is statically typed to 'DBConnection'
            var cmd = CreateCommand(ex); //because 'ex' is dynamic 'cmd' is dynamic
            cmd.Connection = conn; 
            /*
               'cmd.Connection = conn' is bound at runtime and
               the runtime signature of Connection takes a SqlConnection value. 
               You can't assign a statically defined DBConnection to a SqlConnection
               without cast. 
            */
        }
        Console.WriteLine("It will never get here!");
        Console.Read();
        return null;
    }
    

    Options for fixing source (pick only 1):

    1. Cast to statically declare conn as a SqlConnection: using (var conn = (SqlConnection) OpenConnection())

    2. Use runtime type of conn: using (dynamic conn = OpenConnection())

    3. Don't dynamic bind CreateCommand: var cmd = CreateCommand((object)ex);

    4. Statically define cmd: DBCommand cmd = CreateCommand(ex);

提交回复
热议问题