/// <summary>
        /// Writes value of this parameter to stream.
        /// </summary>
        internal void Write(BinaryWriter writer)
        {
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }

            if (Value == null || Value == DBNull.Value)
            {
                throw new InvalidOperationException("Write should not be called on parameters with null value");
            }

            if (IsValidatedCollection)
            {
                var count = GetCollectionCount(Value);
                RowData.Write7BitEncodedInt(writer, count);

                if (count > 0)
                {
                    var enumerator = GetEnumerator(Value);
                    var enumwriter = GetEnumeratorWriter(DbType);

                    enumwriter(writer, enumerator);
                }
            }
            else
            {
                WritePrimitiveValue(writer, DbType, Value);
            }
        }
        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);
            }
        }