/// <summary>
        /// Create flight property values from the specified record
        /// </summary>
        /// <param name="count"></param>
        /// <param name="record"></param>
        /// <returns></returns>
        private List <FlightPropertyValue> CreatePropertyValuesFromRecord(int count, string[] record)
        {
            List <FlightPropertyValue> values = new List <FlightPropertyValue>();

            // Iterate over the fields that relate to flight properties
            foreach (FlightPropertyField field in _fields.Where(f => f is FlightPropertyField))
            {
                // Check we have a value for this one
                if (!string.IsNullOrEmpty(record[field.Index]))
                {
                    // Construct a property value object for it
                    try
                    {
                        FlightPropertyValue value = field.GetPropertyValue(record);
                        values.Add(value);
                    }
                    catch (Exception ex)
                    {
                        LastError = new CsvReaderError
                        {
                            Record    = count,
                            Message   = $"Error getting value for field '{field.Name}' at record {count}",
                            Exception = ex.Message
                        };

                        throw;
                    }
                }
            }

            return(values);
        }
        /// <summary>
        /// Find and return the value of one of the mandatory (non-flight-property)
        /// fields
        /// </summary>
        /// <typeparam name="U"></typeparam>
        /// <param name="count"></param>
        /// <param name="name"></param>
        /// <param name="record"></param>
        /// <returns></returns>
        private U GetMandatoryFieldValue <U>(int count, string name, string[] record) where U : IConvertible
        {
            // Locate the field with this name
            CsvField field = _fields.FirstOrDefault(f => f.Name.Equals(name, StringComparison.OrdinalIgnoreCase));

            if (field == null)
            {
                // Not found, so an an error to the errors collection and throw
                // an exception
                string message = $"Missing field '{name}' at record '{count}'";
                LastError = new CsvReaderError {
                    Record = count, Message = message
                };
                throw new FieldNotFoundException(message);
            }

            U value;

            try
            {
                // Attempt to convert the value for this field to type U
                value = field.Get <U>(record);
            }
            catch (Exception ex)
            {
                LastError = new CsvReaderError
                {
                    Record    = count,
                    Message   = $"Error getting value for field '{name}' at record {count}",
                    Exception = ex.Message
                };

                throw;
            }

            return(value);
        }
        /// <summary>
        /// Use the operator number from the specified record to identify the operator Id
        /// </summary>
        /// <param name="count"></param>
        /// <param name="record"></param>
        /// <returns></returns>
        private int GetOperatorId(int count, string[] record)
        {
            string operatorNumber            = GetMandatoryFieldValue <string>(count, _settings.OperatorColumnName, record);
            IEnumerable <Operator> operators = _operators.Where(o => o.OperatorNumber.Equals(operatorNumber, StringComparison.OrdinalIgnoreCase));

            if (!operators.Any())
            {
                string message = $"Operator number '{operatorNumber}' not found at record {count}";
                LastError = new CsvReaderError {
                    Record = count, Message = message
                };
                throw new OperatorNotFoundException(message);
            }
            else if (operators.Count() > 1)
            {
                string message = $"Operator number '{operatorNumber}' matches more than one operator at record {count}";
                LastError = new CsvReaderError {
                    Record = count, Message = message
                };
                throw new TooManyOperatorsFoundException(message);
            }

            return(operators.First().Id);
        }
        /// <summary>
        /// Use the location name from the specified record to identify the location Id
        /// </summary>
        /// <param name="count"></param>
        /// <param name="record"></param>
        /// <returns></returns>
        private int GetLocationId(int count, string[] record)
        {
            string name = GetMandatoryFieldValue <string>(count, _settings.LocationColumnName, record);
            IEnumerable <Location> locations = _locations.Where(l => l.Name.Contains(name, StringComparison.OrdinalIgnoreCase));

            if (!locations.Any())
            {
                string message = $"Location '{name}' not found at record {count}";
                LastError = new CsvReaderError {
                    Record = count, Message = message
                };
                throw new LocationNotFoundException(message);
            }
            else if (locations.Count() > 1)
            {
                string message = $"Location name '{name}' matches more than one location at record {count}";
                LastError = new CsvReaderError {
                    Record = count, Message = message
                };
                throw new TooManyLocationsFoundException(message);
            }

            return(locations.First().Id);
        }
        /// <summary>
        /// Use the drone name from the specified record to identify the drone Id
        /// </summary>
        /// <param name="count"></param>
        /// <param name="record"></param>
        /// <returns></returns>
        private int GetDroneId(int count, string[] record)
        {
            string name = GetMandatoryFieldValue <string>(count, _settings.DroneColumnName, record);
            IEnumerable <Drone> drones = _drones.Where(d => d.Name.Equals(name, StringComparison.OrdinalIgnoreCase));

            if (!drones.Any())
            {
                string message = $"Drone '{name}' not found at record {count}";
                LastError = new CsvReaderError {
                    Record = count, Message = message
                };
                throw new DroneNotFoundException(message);
            }
            else if (drones.Count() > 1)
            {
                string message = $"Drone name '{name}' matches more than one drone at record {count}";
                LastError = new CsvReaderError {
                    Record = count, Message = message
                };
                throw new TooManyDronesFoundException(message);
            }

            return(drones.First().Id);
        }