public object GetInstance(System.ServiceModel.InstanceContext instanceContext) { SsbConversationContext conversationContext = (SsbConversationContext)OperationContext.Current.IncomingMessageProperties[SsbConstants.SsbConversationMessageProperty]; SqlConnection con = OperationContext.Current.Channel.GetProperty <SsbConversationSender>().GetConnection(); return(GetInstance(conversationContext, con)); }
public object GetInstance(System.ServiceModel.InstanceContext instanceContext, System.ServiceModel.Channels.Message message) { SsbConversationContext conversationContext = (SsbConversationContext)OperationContext.Current.IncomingMessageProperties[SsbConstants.SsbConversationMessageProperty]; SsbConversationGroupReceiver cgr = OperationContext.Current.Channel.GetProperty <SsbConversationGroupReceiver>(); SqlConnection con = cgr.GetConnection(); Guid conversationGroupID = cgr.ConversationGroupId; TService instance = (TService)GetInstance(conversationContext, con); cgr.Closing += delegate(object sender, EventArgs e) { //SsbConversationGroupReceiver cgr = (SsbConversationGroupReceiver)sender; ReleaseInstance(conversationGroupID, instance, con); }; return(instance); }
/// <summary> /// Convenience method for configuraing a callback channel. Since this is not a duplex channel it doesn't /// support the declarative callbacks in the normal WCF method. /// </summary> /// <typeparam name="TContract"></typeparam> /// <returns></returns> public TContract GetCallback<TContract>() { ThrowIfDisposedOrNotOpen(); try { Binding binding = channelListener.CreateResponseBinding(); TContract channel = ChannelFactory<TContract>.CreateChannel(binding,new EndpointAddress(SsbUri.Default)); SsbConversationSender sender = ((IClientChannel)channel).GetProperty<SsbConversationSender>(); sender.SetConnection(con); ((IClientChannel)channel).Open(); SsbConversationContext conversation = OperationContext.Current.IncomingMessageProperties[SsbConstants.SsbConversationMessageProperty] as SsbConversationContext; sender.OpenConversation(conversation.ConversationHandle); return channel; } catch (Exception ex) { throw new CommunicationException("An error occurred while obtaining callback channel: " + ex.Message, ex); } }
/// <summary> /// Ends the Service Broker conversation and sends a custom error message on the conversation. /// Issues this command to SQL SErver /// END CONVERSATION @ConversationHandle WITH ERROR = @errorCode DESCRIPTION = @errorDescription /// </summary> /// <param name="errorCode">The error code passed to END CONVERSATION</param> /// /// <param name="errorDescription">The Error description passed to END CONVERSATION</param> /// public void EndConversationWithError(int errorCode, string errorDescription) { ThrowIfDisposedOrNotOpen(); SsbConversationContext conversation = OperationContext.Current.IncomingMessageProperties[SsbConstants.SsbConversationMessageProperty] as SsbConversationContext; try { string SQL = "END CONVERSATION @ConversationHandle WITH ERROR = @error DESCRIPTION = @description"; SqlCommand cmd = new SqlCommand(SQL, con); cmd.Parameters.Add("@ConversationHandle", SqlDbType.UniqueIdentifier).Value = conversation.ConversationHandle; cmd.Parameters.Add("@error", SqlDbType.Int).Value = errorCode; cmd.Parameters.Add("@description", SqlDbType.NVarChar, 3000).Value = errorDescription; cmd.ExecuteNonQuery(); } catch (SqlException ex) { throw new CommunicationException(String.Format("An exception occurred while ending conversation {0}.", conversation.ConversationHandle), ex); } }
protected abstract TService GetInstance(SsbConversationContext conversationContext, SqlConnection con);
internal byte[] Receive(TimeSpan timeout, BufferManager bm, out int messageLength, out SsbConversationContext conversation,WaitHandle cancelEvent) { ThrowIfDisposedOrNotOpen(); byte[] message = null; conversation = null; messageLength = 0; if (queuedResult != null) { ReceivedMessage r = queuedResult; queuedResult = null; conversation = r.Conversation; messageLength = r.MessageLength; byte[] buf = bm.TakeBuffer(messageLength); Buffer.BlockCopy(r.MessageBody, 0, buf, 0, messageLength); return buf; } try { lock (rdrlock) { //If this is the first time, open the reader, otherwise read the next row if ( rdr == null || !rdr.Read() ) { //the last bactch has been processed. Close the reader. if (rdr != null) { rdr.Close(); } rdr = GetMessageBatch(timeout,cancelEvent); //this is a timeout condition //caused by aborting or closing the reciever if ( rdr == null ) { return null; } //this is a timeout condition caused by the WAITFOR expiring if( !rdr.Read() ) { rdr.Close(); //return the Receiver to it's initial state. rdr = null; return null; } } int i = 0; int conversation_handle = i++; int service_name = i++; int message_type_name = i++; int message_body = i++; int message_sequence_number = i++; Guid conversationHandle = rdr.GetGuid(conversation_handle); string ServiceName = rdr.GetString(service_name); string messageTypeName = rdr.GetString(message_type_name); if (messageTypeName != SsbConstants.SsbEndDialogMessage && messageTypeName != SsbConstants.SsbDialogTimerMessage) { //this eliminates a one copy because the message_body //isn't copied into the row buffer. Instead it's chunked directly //into the message byte[]. // CONSIDER (dbrowne) wraping the reader in a custom stream implementation //and pass that back instead to eliminate another copy. messageLength = (int)rdr.GetBytes(message_body, 0, null, 0, 0); if (bm == null) { message = new byte[messageLength]; } else { message = bm.TakeBuffer(messageLength); } int br = (int)rdr.GetBytes(message_body, 0, message, 0, messageLength); if (br != messageLength) //should never happen { throw new Exception("Failed to read all the message bytes"); } } long sequence = rdr.GetInt64(message_sequence_number); conversation = new SsbConversationContext(conversationHandle, this.cgId, sequence, messageTypeName); if (messageTypeName == SsbConstants.SsbErrorMessage) { System.Xml.XmlDocument doc = new System.Xml.XmlDocument(); doc.Load(new System.IO.MemoryStream(message, 0, messageLength)); System.Xml.XmlNamespaceManager mgr = new System.Xml.XmlNamespaceManager(doc.NameTable); mgr.AddNamespace("er", SsbConstants.SsbErrorMessage); int code = int.Parse(doc.SelectSingleNode("/er:Error/er:Code", mgr).InnerText); string ermsg = doc.SelectSingleNode("/er:Error/er:Description", mgr).InnerText; throw new ProtocolException(string.Format("Service Broker Error Message {0}: {1}", code, ermsg)); } SsbInstrumentation.MessageRecieved(messageLength); return message; //if (messageTypeName == SsbConstants.SsbDialogTimerMessage) //{ // //well now we're running again after a lag, now what? //} } } catch (SqlException ex) { //the timeout will not result in a SqlExecption since the timeout value is passed to WAITFOR RECIEVE //if (!helper.IsTimeRemaining) //{ // throw new TimeoutException(String.Format("Timed out while receiving. Timeout value was {0} seconds", timeout.TotalSeconds), ex); //} throw new CommunicationException(String.Format("An exception occurred while receiving from conversation group {0}.", this.cgId), ex); } }
internal byte[] Receive(TimeSpan timeout, BufferManager bm, out int messageLength, out SsbConversationContext conversation) { return Receive(timeout, bm, out messageLength, out conversation, cancelEvent); }
public void EndConversation() { SsbConversationContext conversation = OperationContext.Current.IncomingMessageProperties[SsbConstants.SsbConversationMessageProperty] as SsbConversationContext; this.EndConversation(conversation.ConversationHandle, this.DefaultCloseTimeout); }