/// <summary> /// Populates <paramref name="this"/> with data read from <paramref name="csvReader"/>. /// </summary> /// <remarks> /// <para> /// If <paramref name="this"/> has columns defined, those columns will be used when populating the data. If no columns have been defined, <paramref name="csvReader"/> must have a /// <see cref="HeaderRecord"/>, which is then used to define the columns for <paramref name="this"/>. If any data record has more values than can fit into the columns defined on /// <paramref name="this"/>, an exception is thrown. /// </para> /// </remarks> /// <param name="this"> /// The <see cref="DataTable"/>. /// </param> /// <param name="csvReader"> /// The <see cref="CsvReader"/>. /// </param> /// <param name="maximumRecords"> /// The maximum number of records to read and add to <paramref name="this"/>. /// </param> /// <returns> /// The number of rows added to <paramref name="this"/> (and therefore the number of data records read from <paramref name="csvReader"/>). /// </returns> public static int Fill(this DataTable @this, CsvReader csvReader, int? maximumRecords) { @this.AssertNotNull("@this"); csvReader.AssertNotNull("csvReader"); exceptionHelper.ResolveAndThrowIf(maximumRecords.GetValueOrDefault() < 0, "maximumRecordsMustBePositive"); if (@this.Columns.Count == 0) { // table has no columns, so we need to use the CSV header record to populate them exceptionHelper.ResolveAndThrowIf(csvReader.HeaderRecord == null, "noColumnsAndNoHeaderRecord"); foreach (var columnName in csvReader.HeaderRecord) { @this.Columns.Add(columnName); } } var remaining = maximumRecords.GetValueOrDefault(int.MaxValue); var buffer = new DataRecord[16]; while (remaining > 0) { var read = csvReader.ReadDataRecords(buffer, 0, Math.Min(buffer.Length, remaining)); if (read == 0) { // no more data break; } for (var i = 0; i < read; ++i) { var record = buffer[i]; exceptionHelper.ResolveAndThrowIf(record.Count > @this.Columns.Count, "moreValuesThanColumns", @this.Columns.Count, record.Count); var recordAsStrings = new string[record.Count]; record.CopyTo(recordAsStrings, 0); @this.Rows.Add(recordAsStrings); } remaining -= read; } return maximumRecords.GetValueOrDefault(int.MaxValue) - remaining; }