public override IEnumerable <IEvent> Save <TAggregate, TSnapshot>(TAggregate aggregate) { using (var db = _connectionFactory.CreateConnection()) { var evts = SaveEvents(db, aggregate).ToList(); if (_snapshottingEnabled && SnapshotRequired(evts, _snapshotFrequency)) { var snapshot = aggregate.ToSnapshot(); var json = _serializer.Serialize(snapshot); var insertSql = SqlCommandFactory.MakeInsert(_sqlEventStoreConfig.SnapshotsTableName, aggregate.Id, snapshot.Version, snapshot.GetType().AssemblyQualifiedName, json); var insert = new SqlCommand(insertSql, db); insert.ExecuteNonQuery(); } return(evts); } }
private IEnumerable <IEvent> SaveEvents(SqlConnection db, IAggregate aggregate) { if (!aggregate.UncommitedEvents().Any()) { return(new List <IEvent>()); } var evtsToSave = aggregate.UncommitedEvents().ToList(); var expected = CalculateExpectedVersion(aggregate, evtsToSave); var transaction = db.BeginTransaction(IsolationLevel.ReadCommitted); try { var sql = SqlCommandFactory.MakeCountEvents(_sqlEventStoreConfig.EventsTableName, aggregate.Id); var getEvents = new SqlCommand(sql, db, transaction); var current = (int)getEvents.ExecuteScalar() - 1; if (expected != current) { throw new AggregateConflictException(aggregate.Id, expected, current); } var insertSql = new StringBuilder(); foreach (var e in evtsToSave) { var version = e.Version; var type = e.GetType().AssemblyQualifiedName; var payload = _serializer.Serialize(e).Replace("'", "''"); var insertCmd = SqlCommandFactory.MakeInsert(_sqlEventStoreConfig.EventsTableName, aggregate.Id, version, type, payload); insertSql.AppendLine(insertCmd); } var insert = new SqlCommand(insertSql.ToString(), db, transaction); try { if (insert.ExecuteNonQuery() != evtsToSave.Count) { throw new AggregateConflictException(aggregate.Id, expected, current); } } catch (Exception ex) { if (ex.Message.Contains("duplicate")) { throw new AggregateConflictException(aggregate.Id, expected, current); } throw; } transaction.Commit(); } catch (Exception) { if (transaction.Connection != null) { transaction.Rollback(); } throw; } return(aggregate.UncommitedEvents()); }