2

我有一个 WCF 客户端,它通过两种方法要求订单确认和 WCF 服务:

1) UpdateOrder - 更新数据库中的订单数据(UpdateOrder 调用来自外部服务)
2) GetConfirmationResult - 保持结果返回,直到订单状态从待处理变为其他状态。

问题是,如何在 WCF 中通知从 UpdateOrder 到 GetConfirmationResult,订单状态已更改?

更新:最好,如果我可以将 InstanceContextMode 保留为 Per-Call。

更新 2:假设可能的订单状态为待处理、已确认、已拒绝。ConfirmOrder 可以将订单状态更改为 Confirmed 或 Rejected,GetConfirmationResult 不应该返回结果,直到它被 Confirm 订单更改。

更新 3:我已经更改了带有序列的图像以显示整个堆栈。

在此处输入图像描述

4

3 回答 3

3

你说你有一个支持这个服务器的数据库。然后它会像这样简单,半伪:

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

您必须坚持下去,因为您提到的是按呼叫实例模式。您不能保留 astatic List<Order>来包含您的待处理订单,只需将它们保存到您的数据库中并将它们添加为待处理,未批准。

于 2012-07-31T07:46:45.823 回答
1

听起来您的问题是基于订单状态在特定时间发生变化的事实,并且只有当该阶段发生变化时,服务消费者才能了解新的订单状态。

这是使用消息传递的完美场景。

与您的 wcf 客户端调用服务不同,服务应该只在订单状态更改时向客户端发送一条消息。然后客户端可以处理该消息(在您的情况下为 ConfirmationResult 消息)。

您可以通过使用 netMsmqBinding 并在接受 msmq 消息的客户端上托管操作来执行此操作。

[OperationContract]
void ReceiveConfirmationResult(ConfirmationResult result);

这要简单得多,因为它完全消除了问题的根源。作为一个额外的好处,服务操作 GetConfirmationResult() 可以被删除,因为它不再需要。

更新

我认为您误解了,因为根据您最新的问题更新,这是使用排队的更强有力的案例。

事件顺序:

  1. 收到订单确认
  2. 服务器状态改变
  3. 服务器应用逻辑来确定是否应将状态更改发送给客户端
  4. 服务器向客户端发送描述状态变化的消息
于 2012-07-31T10:02:08.097 回答
1

目前我已经使用 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;
    }
}
于 2012-08-02T06:46:17.227 回答