/// <summary> /// Evaluates whether a given working order is eligible for a cross with another order. /// </summary> public static void CrossChat(Object[] key, params Object[] parameters) { // An instance of the data model is required for CRUD operations. DataModel dataModel = new DataModel(); // The logic below will examine the order and see if a contra order is available for a match. These values will indicate whether a match is // possible after all the locks have been released. Guid chatId = (Guid)key[0]; // A transaction is required to lock the records and change the data model. using (TransactionScope transactionScope = new TransactionScope()) { // This variable holds context information for the current transaction. DataModelTransaction dataModelTransaction = DataModelTransaction.Current; // This is the working order that will be tested for a possible buyer or seller (contra party). ChatRow chatRow = DataModel.Chat.ChatKey.Find(chatId); if (chatRow == null) { throw new Exception(string.Format("Chat {0} has been deleted", chatId)); } chatRow.AcquireReaderLock(dataModelTransaction); // The match record contains the identifier for the counter party. The counter party is needed in order to create an // entry in the conversation that is private to that user. MatchRow matchRow = DataModel.Match.MatchKey.Find(chatRow.MatchId); matchRow.AcquireReaderLock(dataModelTransaction); // This is the counter party to the match. MatchRow contraMatchRow = DataModel.Match.MatchKey.Find(matchRow.ContraMatchId); contraMatchRow.AcquireReaderLock(dataModelTransaction); // Each side needs a private copy of the conversation in order to pass through the Chinese wall. This will create an entry in the conversation // for the contra side of the conversation. Guid contraChatId = Guid.NewGuid(); DateTime createdTime = DateTime.UtcNow; dataModel.CreateChat( contraMatchRow.BlotterId, contraChatId, createdTime, true, contraMatchRow.MatchId, chatRow.Message); // The working order that triggered this action has completed a scan of the data model and has notified all possible counter parties of the its // new status. Once the transaction is completed, a negotiation session will be started if a new counter party is found. transactionScope.Complete(); } }
public static void CreateChat(ChatInfo[] chatInfos) { // A reference to the data model is required for actions that modify it. DataModel dataModel = new DataModel(); // Everything in this transaction will be committed or rolled back as a unit. using (TransactionScope transactionScope = new TransactionScope()) { // Extract the ambient transaction. DataModelTransaction dataModelTransaction = DataModelTransaction.Current; // This action handles a batch of chat items in a single transaction. foreach (ChatInfo chatInfo in chatInfos) { // These values are required for each chat item added. Guid blotterId = default(Guid); DateTime createdTime = DateTime.UtcNow; // The Match record contains the blotter identifier which is used for filtering. MatchRow matchRow = DataModel.Match.MatchKey.Find(chatInfo.MatchId); try { matchRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout); blotterId = matchRow.BlotterId; } finally { matchRow.ReleaseReaderLock(dataModelTransaction.TransactionId); } // Once the blotter id has been extracted the internal methods can be called to add the chat item. dataModel.CreateChat(blotterId, chatInfo.ChatId, createdTime, false, chatInfo.MatchId, chatInfo.Message); } // If we reached this point the transaction was successful. transactionScope.Complete(); } }