/// <summary>
        /// Converts a sequence of <paramref name="items"/> into a sequence of <see cref="SqlDataRecord"/> using the supplied <paramref name="metaData"/>
        /// </summary>
        internal static IEnumerable <SqlDataRecord> ToDataRecords <T>(this IEnumerable <T> items, SqlMetaData[] metaData)
        {
            Contract.Requires(items != null);
            Contract.Requires(metaData != null);
            Contract.Requires(metaData.Length > 0);
            var key = new TypeAndMetaData(typeof(T), metaData);
            var map = (Func <SqlMetaData[], T, SqlDataRecord>)GetOrAddFunc(key, typeof(T));

            return(items.Select(item => map(metaData, item)));
        }
        /// <summary>
        /// Converts a sequence of <paramref name="items"/> into a <see cref="SqlTable"/> containing a sequence of <see cref="SqlDataRecord"/> using the supplied <paramref name="metaData"/>
        /// </summary>
        /// <remarks><paramref name="extraAction"/> can be used to set additional values on each <see cref="SqlDataRecord"/></remarks>
        public static SqlTable ToSqlTable <T>(this IEnumerable <T> items, SqlTableType type, Action <SqlDataRecord, T> extraAction)
        {
            Contract.Requires(items != null);
            Contract.Requires(type.Columns != null);
            Contract.Requires(!string.IsNullOrWhiteSpace(type.Name));
            Contract.Ensures(Contract.Result <IEnumerable <SqlDataRecord> >() != null);

            var key = new TypeAndMetaData(typeof(T), type.Columns);
            var map = (Func <SqlMetaData[], T, SqlDataRecord>)GetOrAddFunc(key, typeof(T));

            if (items.Any())
            {
                return(new SqlTable(type.Name, ConvertItemsToRecords(items, type.Columns, map, extraAction)));
            }
            else
            {
                return(new SqlTable(type.Name, null)); // SQL will throw and exception if you try to pass an empty enumeration
            }
        }
 static Delegate GetOrAddFunc(TypeAndMetaData key, Type typeT) => Methods.GetOrAdd(key, data => CreateMappingFunc(typeT, data.MetaData));