public void Commit() { _session.Commit(); }
public FactID Save(string domain, FactMemento fact, Guid clientGuid) { // Retry on concurrency failure. while (true) { using (var session = new Session(_connectionString)) { session.BeginTransaction(); // First see if the fact is already in storage. FactID id; if (FindExistingFact(fact, out id, session, readCommitted: true)) { return(id); } // It isn't there, so store it. int typeId = SaveType(session, fact.FactType); session.Command.CommandText = "INSERT Fact (FKTypeID, Data, Hashcode) VALUES (@TypeID, @Data, @Hashcode)"; AddParameter(session.Command, "@TypeID", typeId); AddParameter(session.Command, "@Data", fact.Data); AddParameter(session.Command, "@Hashcode", fact.GetHashCode()); session.Command.ExecuteNonQuery(); session.Command.Parameters.Clear(); session.Command.CommandText = "SELECT @@IDENTITY"; decimal result = (decimal)session.Command.ExecuteScalar(); session.Command.Parameters.Clear(); id.key = (Int64)result; // Store the predecessors. foreach (PredecessorMemento predecessor in fact.Predecessors) { int roleId = SaveRole(session, predecessor.Role); session.Command.CommandText = "INSERT Predecessor (FKFactID, FKRoleID, FKPredecessorFactID, IsPivot) VALUES (@FactID, @RoleID, @PredecessorFactID, @IsPivot)"; AddParameter(session.Command, "@FactID", id.key); AddParameter(session.Command, "@RoleID", roleId); AddParameter(session.Command, "@PredecessorFactID", predecessor.ID.key); AddParameter(session.Command, "@IsPivot", predecessor.IsPivot); session.Command.ExecuteNonQuery(); session.Command.Parameters.Clear(); } // Store a message for each pivot. FactID newFactId = id; List <MessageMemento> pivotMessages = fact.Predecessors .Where(predecessor => predecessor.IsPivot) .Select(predecessor => new MessageMemento(predecessor.ID, newFactId)) .ToList(); // Store messages for each non-pivot. This fact belongs to all predecessors' pivots. string[] nonPivots = fact.Predecessors .Where(predecessor => !predecessor.IsPivot) .Select(predecessor => predecessor.ID.key.ToString()) .ToArray(); List <MessageMemento> nonPivotMessages; if (nonPivots.Length > 0) { string nonPivotGroup = string.Join(",", nonPivots); session.Command.CommandText = string.Format( "SELECT DISTINCT PivotId FROM Message WHERE FactId IN ({0})", nonPivotGroup); List <FactID> predecessorsPivots; using (IDataReader predecessorPivotReader = session.Command.ExecuteReader()) { session.Command.Parameters.Clear(); predecessorsPivots = LoadIDsFromReader(predecessorPivotReader).ToList(); } nonPivotMessages = predecessorsPivots .Select(predecessorPivot => new MessageMemento(predecessorPivot, newFactId)) .ToList(); } else { nonPivotMessages = new List <MessageMemento>(); } int clientId = SaveClient(session, clientGuid); var messages = pivotMessages.Union(nonPivotMessages).Distinct().ToList(); SaveMessages(session, messages, clientId); // Optimistic concurrency check. // Make sure we don't find more than one. var existingFacts = FindExistingFacts(fact, session, readCommitted: false); if (existingFacts.Count == 1) { session.Commit(); if (messages.Any() && PivotAffected != null) { foreach (var message in messages) { PivotAffected(domain, message.PivotId); } } return(id); } else { _retried = true; } } } }