// <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); }