public FactID InsertFact(FactMemento fact, int typeId) { _session.Command.CommandText = "INSERT Fact (FKTypeID, Data, Hashcode) VALUES (@TypeID, @Data, @Hashcode)"; AddParameter("@TypeID", typeId); AddParameter("@Data", fact.Data); AddParameter("@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(); return(new FactID { key = (Int64)result }); }
public List <IdentifiedFactMemento> GetEqualFactsByHashCode(FactMemento memento, bool readCommitted, int typeId) { _session.Command.CommandText = HEAD_SELECT + (readCommitted ? "" : "WITH (NOLOCK) ") + "WHERE f.FKTypeID = @TypeID AND f.Hashcode = @Hashcode " + TAIL_JOIN + "ORDER BY ff.FactID, p.PredecessorID"; AddParameter("@TypeID", typeId); AddParameter("@Hashcode", memento.GetHashCode()); using (var loader = new Loader(_session.Command.ExecuteReader())) { _session.Command.Parameters.Clear(); return(loader.LoadMementos() .Where(im => im.Memento.Equals(memento)) .ToList()); } }
private List <IdentifiedFactMemento> FindExistingFacts(FactMemento memento, Session session, bool readCommitted) { int typeId = SaveType(session, memento.FactType); // Load all candidates that have the same hash code. session.Command.CommandText = HEAD_SELECT + (readCommitted ? "" : "WITH (NOLOCK) ") + "WHERE f.FKTypeID = @TypeID AND f.Hashcode = @Hashcode " + TAIL_JOIN + "ORDER BY ff.FactID, p.PredecessorID"; AddParameter(session.Command, "@TypeID", typeId); AddParameter(session.Command, "@Hashcode", memento.GetHashCode()); using (IDataReader factReader = session.Command.ExecuteReader()) { session.Command.Parameters.Clear(); return(LoadMementosFromReader(factReader).Where(im => im.Memento.Equals(memento)).ToList()); } }
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; } } } }
public FactID InsertFact(FactMemento fact, int typeId) { _session.Command.CommandText = "INSERT Fact (FKTypeID, Data, Hashcode) VALUES (@TypeID, @Data, @Hashcode)"; AddParameter("@TypeID", typeId); AddParameter("@Data", fact.Data); AddParameter("@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(); return new FactID { key = (Int64)result }; }
public List<IdentifiedFactMemento> GetEqualFactsByHashCode(FactMemento memento, bool readCommitted, int typeId) { _session.Command.CommandText = HEAD_SELECT + (readCommitted ? "" : "WITH (NOLOCK) ") + "WHERE f.FKTypeID = @TypeID AND f.Hashcode = @Hashcode " + TAIL_JOIN + "ORDER BY ff.FactID, p.PredecessorID"; AddParameter("@TypeID", typeId); AddParameter("@Hashcode", memento.GetHashCode()); using (var loader = new Loader(_session.Command.ExecuteReader())) { _session.Command.Parameters.Clear(); return loader.LoadMementos() .Where(im => im.Memento.Equals(memento)) .ToList(); } }