private AggregateRootSnapshot MakeSnapshot(SqlDataReader r, SnapshotOrdinal ordinal)
        {
            var type = Type.GetType(r.Field <string>(ordinal.Type));
            var blob = r.Field <string>(ordinal.Blob);

            return(type != null ? _serializer.ReadObject <AggregateRootSnapshot>(type, blob) : null);
        }
        /// <summary>
        /// Gets the latest snapshot.
        /// </summary>
        /// <typeparam name="TAggregateRoot">The type of the aggregate root.</typeparam>
        /// <param name="aggregateID">The aggregate ID.</param>
        /// <returns></returns>
        public AggregateRootSnapshot GetLatestSnapshot <TAggregateRoot>(object aggregateID)
            where TAggregateRoot : AggregateRoot
        {
            using (var connection = new SqlConnection(_connectionString))
            {
                var sql     = string.Format(@"
Select Top 1 Type, Blob
From dbo.[{0}]
	Where (AggregateID = @id)
    And (AggregateType = @aType);", _tableName);
                var command = new SqlCommand(sql, connection)
                {
                    CommandType = CommandType.Text
                };
                command.Parameters.AddRange(new[] {
                    new SqlParameter {
                        ParameterName = "@id", SqlDbType = SqlDbType.NVarChar, Value = aggregateID
                    },
                    new SqlParameter {
                        ParameterName = "@aType", SqlDbType = SqlDbType.NVarChar, Value = typeof(TAggregateRoot).AssemblyQualifiedName
                    }
                });
                connection.Open();
                using (var r = command.ExecuteReader())
                {
                    var ordinal = new SnapshotOrdinal(r, false);
                    return(r.Read() ? MakeSnapshot(r, ordinal) : null);
                }
            }
        }
        /// <summary>
        /// Gets the latest snapshots.
        /// </summary>
        /// <typeparam name="TAggregateRoot">The type of the aggregate root.</typeparam>
        /// <param name="aggregateIDs">The aggregate I ds.</param>
        /// <returns></returns>
        public IEnumerable <AggregateTuple <AggregateRootSnapshot> > GetLatestSnapshots <TAggregateRoot>(IEnumerable <object> aggregateIDs)
            where TAggregateRoot : AggregateRoot
        {
            var xml = new XElement("r", aggregateIDs
                                   .Select(x => new XElement("s",
                                                             new XAttribute("i", x.ToString())))
                                   );

            using (var connection = new SqlConnection(_connectionString))
            {
                var sql     = string.Format(@"
Select Type, Blob
From dbo.[{0}]
    Inner Join @xml.nodes(N'/r/s') _xml(item)
    On (AggregateID = _xml.item.value(N'@i', N'nvarchar(100)'))
    And (AggregateType = @aType);", _tableName);
                var command = new SqlCommand(sql, connection)
                {
                    CommandType = CommandType.Text
                };
                command.Parameters.AddRange(new[] {
                    new SqlParameter {
                        ParameterName = "@aType", SqlDbType = SqlDbType.NVarChar, Value = typeof(TAggregateRoot).AssemblyQualifiedName
                    },
                    new SqlParameter {
                        ParameterName = "@xml", SqlDbType = SqlDbType.Xml, Value = xml.ToString()
                    }
                });
                connection.Open();
                var snapshots = new List <AggregateTuple <AggregateRootSnapshot> >();
                using (var r = command.ExecuteReader())
                {
                    var ordinal = new SnapshotOrdinal(r, true);
                    while (r.Read())
                    {
                        snapshots.Add(MakeSnapshotTuple(r, ordinal));
                    }
                }
                return(snapshots);
            }
        }
        private AggregateTuple <AggregateRootSnapshot> MakeSnapshotTuple(SqlDataReader r, SnapshotOrdinal ordinal)
        {
            var aggregateID = r.Field <string>(ordinal.AggregateID);

            return(new AggregateTuple <AggregateRootSnapshot>
            {
                AggregateID = (_makeAggregateID == null ? aggregateID : _makeAggregateID(aggregateID)),
                Item1 = MakeSnapshot(r, ordinal),
            });
        }