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;
                    }
                }
            }
        }