{"record":{"id":"a041f7ec13d08678","repo":"dotnet/orleans","slug":"value-cannot-be-null-parameter-parameters","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'parameters')","messagePattern":"Value cannot be null\\. \\(Parameter 'parameters'\\)","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/AdoNet/Shared/Storage/RelationalStorageExtensions.cs","lineNumber":62,"sourceCode":"        /// <typeparam name=\"T\"></typeparam>\n        /// <param name=\"storage\">The storage to use.</param>\n        /// <param name=\"tableName\">The table name to against which to execute the query.</param>\n        /// <param name=\"parameters\">The parameters to insert.</param>\n        /// <param name=\"nameMap\">If provided, maps property names from <typeparamref name=\"T\"/> to ones provided in the map.</param>\n        /// <param name=\"onlyOnceColumns\">If given, SQL parameter values for the given <typeparamref name=\"T\"/> property types are generated only once. Effective only when <paramref name=\"useSqlParams\"/> is <em>TRUE</em>.</param>\n        /// <param name=\"useSqlParams\"><em>TRUE</em> if the query should be in parameterized form. <em>FALSE</em> otherwise.</param>\n        /// <param name=\"cancellationToken\">The cancellation token. Defaults to <see cref=\"CancellationToken.None\"/>.</param>\n        /// <returns>The rows affected.</returns>\n        public static Task<int> ExecuteMultipleInsertIntoAsync<T>(this IRelationalStorage storage, string tableName, IEnumerable<T> parameters, IReadOnlyDictionary<string, string>? nameMap = null, IEnumerable<string>? onlyOnceColumns = null, bool useSqlParams = true, CancellationToken cancellationToken = default)\n        {\n            if(string.IsNullOrWhiteSpace(tableName))\n            {\n                throw new ArgumentException(\"The name must be a legal SQL table name\", nameof(tableName));\n            }\n\n            if(parameters == null)\n            {\n                throw new ArgumentNullException(nameof(parameters));\n            }\n\n            var storageConsts = DbConstantsStore.GetDbConstants(storage.InvariantName);\n\n            var startEscapeIndicator = storageConsts.StartEscapeIndicator;\n            var endEscapeIndicator = storageConsts.EndEscapeIndicator;\n\n            //SqlParameters map is needed in case the query needs to be parameterized in order to avoid two\n            //reflection passes as first a query needs to be constructed and after that when a database\n            //command object has been created, parameters need to be provided to them.\n            var sqlParameters = new Dictionary<string, object?>();\n            const string insertIntoValuesTemplate = \"INSERT INTO {0} ({1}) SELECT {2};\";\n            var columns = string.Empty;\n            var values = new List<string>();\n            if(parameters.Any())\n            {\n                //Type and property information are the same for all of the objects.\n                //The following assumes the property names will be retrieved in the same","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/dotnet/orleans/blob/fca799fa70ecb6ad975224271703ca43221f58de/src/AdoNet/Shared/Storage/RelationalStorageExtensions.cs#L44-L80","documentation":"Thrown by RelationalStorageExtensions.ExecuteMultipleInsertIntoAsync<T> when the parameters enumerable is null. The method enumerates parameters to build the column list and value rows via reflection, so null is rejected with ArgumentNullException(nameof(parameters)). An empty enumerable is valid and yields a no-op insert.","triggerScenarios":"Calling ExecuteMultipleInsertIntoAsync with parameters: null, e.g. a caller passed an uninitialized list or a LINQ Where that was never assigned.","commonSituations":"Batching code that returns null instead of an empty list when there is nothing to insert; refactor that swapped an argument; null-coalescing missing at the call site.","solutions":["Pass an empty collection instead of null when there is nothing to insert: parameters ?? Array.Empty<T>().","Initialize list fields and return Enumerable.Empty<T>() from helpers that may have no rows.","Enable nullable reference types to surface null-typed arguments at compile time.","Guard at the boundary: if (parameters is null) return Task.FromResult(0);"],"exampleFix":"// before\nawait storage.ExecuteMultipleInsertIntoAsync(table, parameters: null);\n\n// after\nawait storage.ExecuteMultipleInsertIntoAsync(table, parameters ?? Array.Empty<T>());","handlingStrategy":"validation","validationCode":"var rows = parameters ?? Array.Empty<T>();","typeGuard":"static bool HasParameters<T>(IEnumerable<T>? p) => p is not null;","tryCatchPattern":"try { await storage.ExecuteMultipleInsertIntoAsync(table, rows); }\ncatch (ArgumentNullException ex) when (ex.ParamName == nameof(rows)) { /* pass empty */ }","preventionTips":["Return Enumerable.Empty<T>() from helpers that may have no rows.","Coalesce nulls at the call site: parameters ?? Array.Empty<T>().","Enable nullable reference types."],"tags":["csharp","dotnet","orleans","adonet","argument-validation","null-reference"],"backgroundTag":null,"analyzedSha":"fca799fa70ecb6ad975224271703ca43221f58de","analyzedAt":"2026-08-13T19:55:57.938Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}