Contains a series of Times and Values for an individual signal. Abstract versions of this class should attempt to store the value in its most appropriate format to reduce the amount of conversion that must occur.
        public static DataTable GetTable(this ClientDatabaseBase <HistorianKey, HistorianValue> database, ulong start, ulong stop, IList <ISignalWithName> columns)
        {
            if (columns.Any((x) => !x.HistorianId.HasValue))
            {
                throw new Exception("All columns must be contained in the historian for this function to work.");
            }

            Dictionary <ulong, SignalDataBase> results = database.GetSignals(start, stop, columns);

            int[]            columnPosition = new int[columns.Count];
            object[]         rowValues      = new object[columns.Count + 1];
            SignalDataBase[] signals        = new SignalDataBase[columns.Count];

            DataTable table = new DataTable();

            table.Columns.Add("Time", typeof(DateTime));
            foreach (ISignalWithName signal in columns)
            {
                table.Columns.Add(signal.TagName, typeof(double));
            }

            for (int x = 0; x < columns.Count; x++)
            {
                signals[x] = results[columns[x].HistorianId.Value];
            }

            while (true)
            {
                ulong minDate = ulong.MaxValue;
                for (int x = 0; x < columns.Count; x++)
                {
                    SignalDataBase signal = signals[x];
                    if (signal.Count < columnPosition[x])
                    {
                        minDate = Math.Min(minDate, signals[x].GetDate(columnPosition[x]));
                    }
                }

                rowValues[0] = null;
                for (int x = 0; x < columns.Count; x++)
                {
                    SignalDataBase signal = signals[x];
                    if (signal.Count < columnPosition[x] && minDate == signals[x].GetDate(columnPosition[x]))
                    {
                        ulong  date;
                        double value;
                        signals[x].GetData(columnPosition[x], out date, out value);
                        rowValues[x + 1] = value;
                        columnPosition[x]++;
                    }
                    else
                    {
                        rowValues[x + 1] = null;
                    }
                }

                if (minDate == ulong.MaxValue && rowValues.All((x) => x == null))
                {
                    return(table);
                }
                rowValues[0] = minDate;

                table.Rows.Add(rowValues);
            }
        }
        public static DataTable GetTable(this ClientDatabaseBase<HistorianKey, HistorianValue> database, ulong start, ulong stop, IList<ISignalWithName> columns)
        {
            if (columns.Any((x) => !x.HistorianId.HasValue))
            {
                throw new Exception("All columns must be contained in the historian for this function to work.");
            }

            Dictionary<ulong, SignalDataBase> results = database.GetSignals(start, stop, columns);
            int[] columnPosition = new int[columns.Count];
            object[] rowValues = new object[columns.Count + 1];
            SignalDataBase[] signals = new SignalDataBase[columns.Count];

            DataTable table = new DataTable();
            table.Columns.Add("Time", typeof(DateTime));
            foreach (ISignalWithName signal in columns)
            {
                table.Columns.Add(signal.TagName, typeof(double));
            }

            for (int x = 0; x < columns.Count; x++)
            {
                signals[x] = results[columns[x].HistorianId.Value];
            }

            while (true)
            {
                ulong minDate = ulong.MaxValue;
                for (int x = 0; x < columns.Count; x++)
                {
                    SignalDataBase signal = signals[x];
                    if (signal.Count < columnPosition[x])
                    {
                        minDate = Math.Min(minDate, signals[x].GetDate(columnPosition[x]));
                    }
                }

                rowValues[0] = null;
                for (int x = 0; x < columns.Count; x++)
                {
                    SignalDataBase signal = signals[x];
                    if (signal.Count < columnPosition[x] && minDate == signals[x].GetDate(columnPosition[x]))
                    {
                        ulong date;
                        double value;
                        signals[x].GetData(columnPosition[x], out date, out value);
                        rowValues[x + 1] = value;
                        columnPosition[x]++;
                    }
                    else
                    {
                        rowValues[x + 1] = null;
                    }
                }

                if (minDate == ulong.MaxValue && rowValues.All((x) => x == null))
                    return table;
                rowValues[0] = minDate;

                table.Rows.Add(rowValues);
            }
        }