// <summary>
        // Constructs a SqlCeParameter
        // </summary>
        internal static DbParameter CreateSqlCeParameter(
            string name, TypeUsage type, object value, bool ignoreMaxLengthFacet, bool isLocalProvider)
        {
            var rdpSqlCeParameter = Type.GetType(RemoteProvider.SqlCeParameter);

            // No other parameter type is supported.
            //
            DebugCheck.NotNull(type);

            int? size;
            byte?precision;
            byte?scale;

            var result = isLocalProvider
                             ? new SqlCeParameter()
                             : (DbParameter)RemoteProviderHelper.CreateRemoteProviderType(RemoteProvider.SqlCeParameter);

            result.ParameterName = name;
            result.Value         = value;

            // .Direction
            // parameter.Direction - take the default. we don't support output parameters.
            result.Direction = ParameterDirection.Input;

            // .Size, .Precision, .Scale and .SqlDbType
            var sqlDbType = GetSqlDbType(type, out size, out precision, out scale);

            // Skip guessing the parameter type (only for strings & blobs) if parameter size is not available
            // Instead, let QP take proper guess at execution time with available details.
            //
            if ((null != size) ||
                (!TypeSemantics.IsPrimitiveType(type, PrimitiveTypeKind.String) &&
                 !TypeSemantics.IsPrimitiveType(type, PrimitiveTypeKind.Binary)))
            {
                if (isLocalProvider)
                {
                    var sqlCeParameter = (SqlCeParameter)result;
                    if (sqlCeParameter.SqlDbType != sqlDbType)
                    {
                        sqlCeParameter.SqlDbType = sqlDbType;
                    }
                }
                else
                {
                    // Remote Provider is loaded by reflection. As SqlDbType is not part of the base interface
                    // We need to access this using reflection only.
                    var rdpType = RemoteProviderHelper.GetRemoteProviderType(RemoteProvider.SqlCeParameter);
                    var rdpInfo = rdpType.GetProperty("SqlDbType");
                    rdpInfo.SetValue(result, sqlDbType, null);
                }
            }

            // Note that we overwrite 'facet' parameters where either the value is different or
            // there is an output parameter. This is because output parameters in SqlClient have their
            // facets clobbered if they are implicitly set (e.g. if the Precision was implicitly set
            // by setting the value)
            if (!ignoreMaxLengthFacet &&
                size.HasValue &&
                (result.Size != size.Value))
            {
                result.Size = size.Value;
            }

            if (precision.HasValue &&
                (((IDbDataParameter)result).Precision != precision.Value))
            {
                ((IDbDataParameter)result).Precision = precision.Value;
            }
            if (scale.HasValue &&
                (((IDbDataParameter)result).Scale != scale.Value))
            {
                ((IDbDataParameter)result).Scale = scale.Value;
            }

            // .IsNullable
            var isNullable = TypeSemantics.IsNullable(type);

            if (isNullable != result.IsNullable)
            {
                result.IsNullable = isNullable;
            }

            return(result);
        }
        private DbCommand CreateCommand(DbProviderManifest providerManifest, DbCommandTree commandTree)
        {
            // DEVNOTE/CAUTION: This method could be called either from Remote or Local Provider.
            // Ensure that the code works well with the both provider types.
            // The methods called from the below code also need to be capable
            // of handling both provider types.
            //
            // NOTE: Remote Provider is loaded at runtime, if available.
            // This is done to remove hard dependency on Remote Provider and
            // it might not be present in all scenarios. All Remote Provider
            // type checks need to be done using RemoteProviderHelper class.
            //

            Check.NotNull(providerManifest, "providerManifest");
            Check.NotNull(commandTree, "commandTree");

            if (commandTree is DbFunctionCommandTree)
            {
                throw ADP1.NotSupported(EntityRes.GetString(EntityRes.StoredProceduresNotSupported));
            }

            var command = _isLocalProvider
                              ? new SqlCeMultiCommand()
                              : (DbCommand)RemoteProviderHelper.CreateRemoteProviderType(RemoteProvider.SqlCeCommand);

            command.Connection = null; // don't hold on to the connection when we're going to cache this forever;

            List <DbParameter> parameters;
            CommandType        commandType;

            var commandTexts = SqlGenerator.GenerateSql(commandTree, out parameters, out commandType, _isLocalProvider);

            if (_isLocalProvider)
            {
                Debug.Assert(command is SqlCeMultiCommand, "SqlCeMultiCommand expected");
                // Set the multiple command texts for the command object
                ((SqlCeMultiCommand)command).CommandTexts = commandTexts;
            }
            else
            {
                // Set the command text for the RDP case.
                Debug.Assert(commandTexts.Length == 1, "BatchQueries are not supported in designer scenarios");
                command.CommandText = commandTexts[0];
            }

            command.CommandType = commandType;

            // Now make sure we populate the command's parameters from the CQT's parameters:
            //
            foreach (var queryParameter in commandTree.Parameters)
            {
                DbParameter parameter;
                const bool  ignoreMaxLengthFacet = false;
                parameter = CreateSqlCeParameter(
                    queryParameter.Key, queryParameter.Value, DBNull.Value, ignoreMaxLengthFacet, _isLocalProvider);
                command.Parameters.Add(parameter);
            }

            // Now add parameters added as part of SQL gen (note: this feature is only safe for DML SQL gen which
            // does not support user parameters, where there is no risk of name collision)
            //
            if (null != parameters &&
                0 < parameters.Count)
            {
                if (!(commandTree is DbDeleteCommandTree ||
                      commandTree is DbInsertCommandTree ||
                      commandTree is DbUpdateCommandTree))
                {
                    throw ADP1.InternalError(ADP1.InternalErrorCode.SqlGenParametersNotPermitted);
                }

                foreach (var parameter in parameters)
                {
                    command.Parameters.Add(parameter);
                }
            }

            return(command);
        }