简体   繁体   English

WCF-两种方法之间的通信

[英]WCF - communication between two methods

I have a WCF client, that asks for order confirmation and WCF service with two methods: 我有一个WCF客户端,它要求通过两种方法进行订单确认和WCF服务:

1) UpdateOrder - updates order data in database (UpdateOrder call comes from external service) 1)UpdateOrder-更新数据库中的订单数据(UpdateOrder调用来自外部服务)
2) GetConfirmationResult - which holds return of result till order status will change from pending to something else. 2)GetConfirmationResult-保留结果的返回,直到订单状态从待处理变为其他为止。

Question is, how to make notification from UpdateOrder to GetConfirmationResult, that order status has changed, in WCF? 问题是,在WCF中,如何从UpdateOrder通知到GetConfirmationResult,订单状态已更改?

Update: would be best, if I could leave InstanceContextMode as Per-Call. 更新:如果我可以将InstanceContextMode保留为按调用,那将是最好的。

Update 2: Let's say possible order statuses are Pending, Confirmed, Rejected. 更新2:假设可能的订单状态为“待定”,“已确认”,“已拒绝”。 ConfirmOrder may change order status to Confirmed or Rejected, GetConfirmationResult should not return result until it is changed by Confirm order. ConfirmOrder可能会将订单状态更改为Confirmed或Rejected,GetConfirmationResult不会返回结果,除非由Confirm Order对其进行更改。

Update 3: I've changed image with sequence to display whole stack. 更新3:我更改了图像的顺序以显示整个堆栈。

在此处输入图片说明

You say you have a database backing this server. 您说您有一个支持此服务器的数据库。 Then it'll be as simple as this, semi-psuedo: 然后它将像半伪一样简单:

public YourService : YourServiceInterface
{
    public void UpdateOrder(Order order)
    {
        using (context = new DatabaseContext())
        {
            context.Orders.Where(o => o.ID == order.ID).First().IsConfirmed = order.IsConfirmed;
            context.SaveChanges();
        }
    }

    public Boolean? GetConfirmationResult(Order order)
    {
        using (context = new DatabaseContext())
        {
            return context.Orders.Where(o => o.ID == order.ID).First().IsConfirmed;
        }
    }   
}

You'll have to persist it, since you're mentioning a per call instance mode. 您必须坚持下去,因为您提到的是每个呼叫实例模式。 You can't keep a static List<Order> to contain your pending orders, simply persist them to your database and add them as pending, not approved. 您不能保留static List<Order>来包含您的待处理订单,只需将它们持久保存到数据库中,然后将它们添加为待处理(未批准)即可。

It sounds like your problem is based on the fact that the order state changes at certain times and only when that stage change happens is it relevant for the service consumer to know about the new order state. 听起来您的问题是基于以下事实:订单状态在某些时间发生了变化,只有当阶段更改发生时,服务使用者才知道新的订单状态。

This is a perfect scenario for using messaging. 这是使用消息传递的理想方案。

Rather than your wcf client calling the service, the service should just send a message to the client when the state of the order changes. 当订单状态更改时,该服务应仅向该客户端发送消息,而不是由wcf客户端调用该服务。 The client can then process the message (in your case a ConfirmationResult message). 然后,客户端可以处理该消息(在您的情况下为ConfirmationResult消息)。

You can do this by using the netMsmqBinding and host an operation on the client which accepts a msmq message. 您可以通过使用netMsmqBinding来做到这一点,并在接受msmq消息的客户端上托管一个操作。

[OperationContract]
void ReceiveConfirmationResult(ConfirmationResult result);

This is far simpler as it removes the source of your problem entirely. 这要简单得多,因为它可以完全消除问题的根源。 As an added benefit the service operation GetConfirmationResult() can be removed as it is no longer needed. 作为一项附加好处,可以删除服务操作GetConfirmationResult(),因为它不再需要。

UPDATE UPDATE

I think you misunderstand because based on your latest question update this is an even stronger case for using queueing. 我认为您会误解,因为基于最新的问题更新,这是使用排队的一个更好的案例。

Order of events: 事件顺序:

  1. Order confirmation received 收到订单确认
  2. The server state changes 服务器状态更改
  3. The server applies logic to work out if a state change should be sent to the clients 如果状态更改应发送到客户端,服务器将应用逻辑来计算
  4. The Server sends a message to the client describing the state change 服务器向客户端发送一条消息,描述状态变化

At the moment I've solved it using EventWaitHandle - not sure if it is the best way, but it looks quite clean, nicely supports timeout and is quite testable. 目前,我已经使用EventWaitHandle解决了它-不确定这是否是最好的方法,但是它看起来很干净,可以很好地支持超时并且可以测试。

public class TestClass 
{
    public static event OrderUpdateHandler UpdatedOrder;

    public void UpdateData(Order order) 
    {
        // ...

        OnOrderUpdated(args);
    }

    public Order GetConfirmedOrder(int id, TimeSpan waitToConfirm) 
    {
        var order = GetOrderFromDatabase();

        if (order.Status == OrderStatus.Pending) 
        {
             var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset);

             UpdatedOrderHandler waiter = (s, e) =>
             {
                if (e.Order.Id == id)
                {
                    order = e.Order;
                    eventHandle.Set();
                }
            };

            UpdatedOrder += waiter;

            if (!eventHandle.WaitOne(waitToConfirm))
            {                
                return order;
            }

            OrderUpdated -= waiter;
        }

        return order;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM