private static void WritePrimitiveValue(BinaryWriter writer, DbType dbType, object value)
        {
            switch (dbType)
            {
                    //case DbType.VarNumeric:
                    //    break;
                case DbType.AnsiString:
                case DbType.String:
                case DbType.AnsiStringFixedLength:
                case DbType.StringFixedLength:
                case DbType.Xml:
                    {
                        var data = (string) value;
                        var len = data.Length; // we don't expect null values here
                        RowData.Write7BitEncodedInt(writer, len);
                        for (var i = 0; i < len; i++)
                        {
                            RowData.Write7BitEncodedInt(writer, data[i]);
                        }
                    }
                    break;

                case DbType.Binary:
                case DbType.Object:
                    {
                        var data = (byte[]) value;
                        var len = data.Length; // we don't expect null values here
                        RowData.Write7BitEncodedInt(writer, len);
                        if (len > 0)
                        {
                            writer.Write(data, 0, data.Length);
                        }
                    }
                    break;

                case DbType.Byte:
                    writer.Write((Byte) value);
                    break;

                case DbType.Boolean:
                    writer.Write((bool) value);
                    break;

                case DbType.Time:
                    writer.Write(((TimeSpan)value).Ticks);
                    break;

                case DbType.Date:
                case DbType.DateTime2:
                case DbType.DateTime:
                    writer.Write(((DateTime) value).ToBinary());
                    break;

                case DbType.Currency:
                case DbType.Decimal:
                    writer.Write((Decimal) value);
                    break;

                case DbType.Double:
                    writer.Write((Double) value);
                    break;

                case DbType.Guid:
                    {
                        var curr = new RowData.ValueHolder16Bytes {AsGuid = (Guid) value};
                        writer.Write(curr.Lo);
                        writer.Write(curr.Hi);
                    }
                    break;

                case DbType.Int16:
                    writer.Write((Int16) value);
                    break;

                case DbType.Int32:
                    writer.Write((Int32) value);
                    break;

                case DbType.Int64:
                    writer.Write((Int64) value);
                    break;

                case DbType.SByte:
                    writer.Write((SByte) value);
                    break;

                case DbType.Single:
                    writer.Write((Single)value);
                    break;

                case DbType.UInt16:
                    writer.Write((UInt16) value);
                    break;

                case DbType.UInt32:
                    writer.Write((UInt32) value);
                    break;

                case DbType.UInt64:
                    writer.Write((UInt64) value);
                    break;

                case DbType.DateTimeOffset:
                    {
                        var curr = new RowData.ValueHolder16Bytes { AsDateTimeOffset = (DateTimeOffset)value };
                        writer.Write(curr.Lo);
                        writer.Write(curr.Hi);
                    }
                    break;

                default:
                    throw new DataException("Invalid DbType: " + dbType);
            }
        }
        private static Action <BinaryWriter, object> GetEnumeratorWriter(DbType dbType)
        {
            switch (dbType)
            {
            //case DbType.VarNumeric:
            //    break;
            case DbType.AnsiString:
            case DbType.String:
            case DbType.AnsiStringFixedLength:
            case DbType.StringFixedLength:
            case DbType.Xml:
                return((writer, untyped) =>
                {
                    var typed = (IEnumerator <string>)untyped;
                    while (typed.MoveNext())
                    {
                        var data = typed.Current;
                        var len = data == null ? -1 : data.Length;
                        RowData.Write7BitEncodedInt(writer, len);
                        for (var i = 0; i < len; i++)
                        {
                            RowData.Write7BitEncodedInt(writer, data[i]);
                        }
                    }
                });

            case DbType.Binary:
            case DbType.Object:
                return((writer, untyped) =>
                {
                    var typed = (IEnumerator <byte[]>)untyped;
                    while (typed.MoveNext())
                    {
                        var data = typed.Current;
                        var len = data == null ? -1 : data.Length;
                        RowData.Write7BitEncodedInt(writer, len);
                        if (len > 0)
                        {
                            writer.Write(data, 0, data.Length);
                        }
                    }
                });

            case DbType.Byte:
                return((writer, untyped) =>
                {
                    var typed = (IEnumerator <Byte>)untyped;
                    while (typed.MoveNext())
                    {
                        writer.Write(typed.Current);
                    }
                });

            case DbType.Boolean:
                return((writer, untyped) =>
                {
                    var typed = (IEnumerator <Boolean>)untyped;
                    while (typed.MoveNext())
                    {
                        writer.Write(typed.Current);
                    }
                });

            case DbType.Time:
                return((writer, untyped) =>
                {
                    var typed = (IEnumerator <TimeSpan>)untyped;
                    while (typed.MoveNext())
                    {
                        writer.Write(typed.Current.Ticks);
                    }
                });

            case DbType.Date:
            case DbType.DateTime2:
            case DbType.DateTime:
                return((writer, untyped) =>
                {
                    var typed = (IEnumerator <DateTime>)untyped;
                    while (typed.MoveNext())
                    {
                        writer.Write(typed.Current.ToBinary());
                    }
                });

            case DbType.Currency:
            case DbType.Decimal:
                return((writer, untyped) =>
                {
                    var typed = (IEnumerator <Decimal>)untyped;
                    while (typed.MoveNext())
                    {
                        writer.Write(typed.Current);
                    }
                });

            case DbType.Double:
                return((writer, untyped) =>
                {
                    var typed = (IEnumerator <Double>)untyped;
                    while (typed.MoveNext())
                    {
                        writer.Write(typed.Current);
                    }
                });

            case DbType.Guid:
                return((writer, untyped) =>
                {
                    var typed = (IEnumerator <Guid>)untyped;
                    var curr = new RowData.ValueHolder16Bytes();
                    while (typed.MoveNext())
                    {
                        curr.AsGuid = typed.Current;
                        writer.Write(curr.Lo);
                        writer.Write(curr.Hi);
                    }
                });

            case DbType.Int16:
                return((writer, untyped) =>
                {
                    var typed = (IEnumerator <Int16>)untyped;
                    while (typed.MoveNext())
                    {
                        writer.Write(typed.Current);
                    }
                });

            case DbType.Int32:
                return((writer, untyped) =>
                {
                    var typed = (IEnumerator <Int32>)untyped;
                    while (typed.MoveNext())
                    {
                        writer.Write(typed.Current);
                    }
                });

            case DbType.Int64:
                return((writer, untyped) =>
                {
                    var typed = (IEnumerator <Int64>)untyped;
                    while (typed.MoveNext())
                    {
                        writer.Write(typed.Current);
                    }
                });

            case DbType.SByte:
                return((writer, untyped) =>
                {
                    var typed = (IEnumerator <SByte>)untyped;
                    while (typed.MoveNext())
                    {
                        writer.Write(typed.Current);
                    }
                });

            case DbType.Single:
                return((writer, untyped) =>
                {
                    var typed = (IEnumerator <Single>)untyped;
                    while (typed.MoveNext())
                    {
                        writer.Write(typed.Current);
                    }
                });

            case DbType.UInt16:
                return((writer, untyped) =>
                {
                    var typed = (IEnumerator <UInt16>)untyped;
                    while (typed.MoveNext())
                    {
                        writer.Write(typed.Current);
                    }
                });

            case DbType.UInt32:
                return((writer, untyped) =>
                {
                    var typed = (IEnumerator <UInt32>)untyped;
                    while (typed.MoveNext())
                    {
                        writer.Write(typed.Current);
                    }
                });

            case DbType.UInt64:
                return((writer, untyped) =>
                {
                    var typed = (IEnumerator <UInt64>)untyped;
                    while (typed.MoveNext())
                    {
                        writer.Write(typed.Current);
                    }
                });

            case DbType.DateTimeOffset:
                return((writer, untyped) =>
                {
                    var typed = (IEnumerator <DateTimeOffset>)untyped;
                    var curr = new RowData.ValueHolder16Bytes();
                    while (typed.MoveNext())
                    {
                        curr.AsDateTimeOffset = typed.Current;
                        writer.Write(curr.Lo);
                        writer.Write(curr.Hi);
                    }
                });

            default:
                throw new DataException("Invalid DbType: " + dbType);
            }
        }
        private static Action<BinaryWriter, object> GetEnumeratorWriter(DbType dbType)
        {
            switch (dbType)
            {
                //case DbType.VarNumeric:
                //    break;
                case DbType.AnsiString:
                case DbType.String:
                case DbType.AnsiStringFixedLength:
                case DbType.StringFixedLength:
                case DbType.Xml:
                    return (writer, untyped) =>
                        {
                            var typed = (IEnumerator<string>) untyped;
                            while (typed.MoveNext())
                            {
                                var data = typed.Current;
                                var len = data == null ? -1 : data.Length;
                                RowData.Write7BitEncodedInt(writer, len);
                                for (var i = 0; i < len; i++)
                                {
                                    RowData.Write7BitEncodedInt(writer, data[i]);
                                }
                            }
                        };

                case DbType.Binary:
                case DbType.Object:
                    return (writer, untyped) =>
                        {
                            var typed = (IEnumerator<byte[]>) untyped;
                            while (typed.MoveNext())
                            {
                                var data = typed.Current;
                                var len = data == null ? -1 : data.Length;
                                RowData.Write7BitEncodedInt(writer, len);
                                if (len > 0)
                                {
                                    writer.Write(data, 0, data.Length);
                                }
                            }
                        };

                case DbType.Byte:
                    return (writer, untyped) =>
                    {
                        var typed = (IEnumerator<Byte>)untyped;
                        while (typed.MoveNext())
                        {
                            writer.Write(typed.Current);
                        }
                    };

                case DbType.Boolean:
                    return (writer, untyped) =>
                    {
                        var typed = (IEnumerator<Boolean>)untyped;
                        while (typed.MoveNext())
                        {
                            writer.Write(typed.Current);
                        }
                    };

                case DbType.Time:
                    return (writer, untyped) =>
                    {
                        var typed = (IEnumerator<TimeSpan>) untyped;
                        while (typed.MoveNext())
                        {
                            writer.Write(typed.Current.Ticks);
                        }
                    };

                case DbType.Date:
                case DbType.DateTime2:
                case DbType.DateTime:
                    return (writer, untyped) =>
                    {
                        var typed = (IEnumerator<DateTime>)untyped;
                        while (typed.MoveNext())
                        {
                            writer.Write(typed.Current.ToBinary());
                        }
                    };

                case DbType.Currency:
                case DbType.Decimal:
                    return (writer, untyped) =>
                    {
                        var typed = (IEnumerator<Decimal>)untyped;
                        while (typed.MoveNext())
                        {
                            writer.Write(typed.Current);
                        }
                    };

                case DbType.Double:
                    return (writer, untyped) =>
                    {
                        var typed = (IEnumerator<Double>)untyped;
                        while (typed.MoveNext())
                        {
                            writer.Write(typed.Current);
                        }
                    };

                case DbType.Guid:
                    return (writer, untyped) =>
                    {
                        var typed = (IEnumerator<Guid>)untyped;
                        var curr = new RowData.ValueHolder16Bytes();
                        while (typed.MoveNext())
                        {
                            curr.AsGuid = typed.Current;
                            writer.Write(curr.Lo);
                            writer.Write(curr.Hi);
                        }
                    };

                case DbType.Int16:
                    return (writer, untyped) =>
                    {
                        var typed = (IEnumerator<Int16>)untyped;
                        while (typed.MoveNext())
                        {
                            writer.Write(typed.Current);
                        }
                    };

                case DbType.Int32:
                    return (writer, untyped) =>
                    {
                        var typed = (IEnumerator<Int32>)untyped;
                        while (typed.MoveNext())
                        {
                            writer.Write(typed.Current);
                        }
                    };

                case DbType.Int64:
                    return (writer, untyped) =>
                    {
                        var typed = (IEnumerator<Int64>)untyped;
                        while (typed.MoveNext())
                        {
                            writer.Write(typed.Current);
                        }
                    };

                case DbType.SByte:
                    return (writer, untyped) =>
                    {
                        var typed = (IEnumerator<SByte>)untyped;
                        while (typed.MoveNext())
                        {
                            writer.Write(typed.Current);
                        }
                    };

                case DbType.Single:
                    return (writer, untyped) =>
                    {
                        var typed = (IEnumerator<Single>)untyped;
                        while (typed.MoveNext())
                        {
                            writer.Write(typed.Current);
                        }
                    };

                case DbType.UInt16:
                    return (writer, untyped) =>
                    {
                        var typed = (IEnumerator<UInt16>)untyped;
                        while (typed.MoveNext())
                        {
                            writer.Write(typed.Current);
                        }
                    };

                case DbType.UInt32:
                    return (writer, untyped) =>
                    {
                        var typed = (IEnumerator<UInt32>)untyped;
                        while (typed.MoveNext())
                        {
                            writer.Write(typed.Current);
                        }
                    };

                case DbType.UInt64:
                    return (writer, untyped) =>
                    {
                        var typed = (IEnumerator<UInt64>)untyped;
                        while (typed.MoveNext())
                        {
                            writer.Write(typed.Current);
                        }
                    };

                case DbType.DateTimeOffset:
                    return (writer, untyped) =>
                    {
                        var typed = (IEnumerator<DateTimeOffset>)untyped;
                        var curr = new RowData.ValueHolder16Bytes();
                        while (typed.MoveNext())
                        {
                            curr.AsDateTimeOffset = typed.Current;
                            writer.Write(curr.Lo);
                            writer.Write(curr.Hi);
                        }
                    };
                default:
                    throw new DataException("Invalid DbType: " + dbType);
            }
        }
        private static void WritePrimitiveValue(BinaryWriter writer, DbType dbType, object value)
        {
            switch (dbType)
            {
            //case DbType.VarNumeric:
            //    break;
            case DbType.AnsiString:
            case DbType.String:
            case DbType.AnsiStringFixedLength:
            case DbType.StringFixedLength:
            case DbType.Xml:
            {
                var data = (string)value;
                var len  = data.Length;        // we don't expect null values here
                RowData.Write7BitEncodedInt(writer, len);
                for (var i = 0; i < len; i++)
                {
                    RowData.Write7BitEncodedInt(writer, data[i]);
                }
            }
            break;

            case DbType.Binary:
            case DbType.Object:
            {
                var data = (byte[])value;
                var len  = data.Length;        // we don't expect null values here
                RowData.Write7BitEncodedInt(writer, len);
                if (len > 0)
                {
                    writer.Write(data, 0, data.Length);
                }
            }
            break;

            case DbType.Byte:
                writer.Write((Byte)value);
                break;

            case DbType.Boolean:
                writer.Write((bool)value);
                break;

            case DbType.Time:
                writer.Write(((TimeSpan)value).Ticks);
                break;

            case DbType.Date:
            case DbType.DateTime2:
            case DbType.DateTime:
                writer.Write(((DateTime)value).ToBinary());
                break;

            case DbType.Currency:
            case DbType.Decimal:
                writer.Write((Decimal)value);
                break;

            case DbType.Double:
                writer.Write((Double)value);
                break;

            case DbType.Guid:
            {
                var curr = new RowData.ValueHolder16Bytes {
                    AsGuid = (Guid)value
                };
                writer.Write(curr.Lo);
                writer.Write(curr.Hi);
            }
            break;

            case DbType.Int16:
                writer.Write((Int16)value);
                break;

            case DbType.Int32:
                writer.Write((Int32)value);
                break;

            case DbType.Int64:
                writer.Write((Int64)value);
                break;

            case DbType.SByte:
                writer.Write((SByte)value);
                break;

            case DbType.Single:
                writer.Write((Single)value);
                break;

            case DbType.UInt16:
                writer.Write((UInt16)value);
                break;

            case DbType.UInt32:
                writer.Write((UInt32)value);
                break;

            case DbType.UInt64:
                writer.Write((UInt64)value);
                break;


            case DbType.DateTimeOffset:
            {
                var curr = new RowData.ValueHolder16Bytes {
                    AsDateTimeOffset = (DateTimeOffset)value
                };
                writer.Write(curr.Lo);
                writer.Write(curr.Hi);
            }
            break;

            default:
                throw new DataException("Invalid DbType: " + dbType);
            }
        }