如何在 WCF 服务方法调用之间保留值?

How can I preserve values between WCF service methods calling?

我有这个 WCF 服务 class:

public partial class OhmioSVC: IOhmioSVC_Security
{
    // Porque no funciona si la variable no es estatica?
    private static ConnectionBusiness _conn = new ConnectionBusiness();

    public ConnectionBusiness Conn
    {
        get
        {
            return _conn;
        }
    }

    public void Connect(string Usuario, string Password, string DataBase)
    {            
        Conn.ObtenerTicket (Usuario, Password, DataBase);                        
    }

    public List<Errores> GetErrors()
    {
        return Conn.MyErrors;            
    }        
}

如您所见,_conn 被定义为静态的,因为我需要在调用之间保留他的值。如果我删除 "static",并调用方法 Connect(创建 _conn 对象)然后调用 getErrores _conn 变量由于某种原因为空。

问题在于,如果我错过调用 "connect" 方法,我想抛出异常,但 _conn 仍然从上次调用中获取值。我知道我在这里做错了什么,但我看不到另一种选择。有什么想法吗?

谢谢

默认情况下,为创建的每个新 session 实例化 WCF 服务 class。对于某些不支持会话的绑定,然后 "session" 仅跨越单个调用,这意味着对于来自客户端的两个调用(一个用于 Connect,一个用于 GetErrors),将是创建的 OhmioSVC class 的两个实例,这就是为什么如果您不将 ConnectionBusiness 属性 指定为静态,将创建其中两个,您将得到你看到的结果。

您需要告诉 WCF 您需要服务合同中的会话。您可以通过在服务合同声明中添加 SessionMode 属性 来做到这一点:

[ServiceContract(SessionMode = SessionMode.Required)]
public interface IOhmio_Security
{
    [OperationContract]
    void Connect(string user, string password, string db);
    [OperationContract]
    List<string> GetErrors();
}

如果您拥有它,并且您使用了不支持会话的绑定(例如 BasicHttpBinding),那么您的服务将无法打开 - 然后您需要更改为支持会话的绑定(例如 WSHttpBinding) .下面的代码显示了一个会话有效的示例:

public class Whosebug_31541498
{
    class ConnectionBusiness
    {
        List<string> errors = new List<string>();
        public void ObtenerTicket(string user, string password, string db)
        {
            errors.Add(string.Format("ObtenerTicket called: {0}, {1}, {2}", user, password, db));
        }
        public List<string> MyErrors
        {
            get
            {
                var result = new List<string>(this.errors);
                errors.Clear();
                if (result.Count == 0)
                {
                    result.Add("No errors!");
                }
                return result;
            }
        }
    }
    [ServiceContract(SessionMode = SessionMode.Required)]
    public interface IOhmio_Security
    {
        [OperationContract]
        void Connect(string user, string password, string db);
        [OperationContract]
        List<string> GetErrors();
    }
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
    public class OhmioSVC : IOhmio_Security
    {
        private ConnectionBusiness _conn = new ConnectionBusiness();
        public void Connect(string user, string password, string db)
        {
            _conn.ObtenerTicket(user, password, db);
        }

        public List<string> GetErrors()
        {
            return _conn.MyErrors;
        }
    }
    static Binding GetBinding()
    {
        // var result = new BasicHttpBinding(); // This will not work, as it doesn't support sessions
        var result = new WSHttpBinding(); // This will work
        return result;
    }
    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(OhmioSVC), new Uri(baseAddress));
        host.AddServiceEndpoint(typeof(IOhmio_Security), GetBinding(), "");
        host.Open();
        Console.WriteLine("Host opened");

        var factory = new ChannelFactory<IOhmio_Security>(GetBinding(), new EndpointAddress(baseAddress));
        var proxy = factory.CreateChannel();

        proxy.Connect("user", "pwd", "db");
        var errors = proxy.GetErrors();
        Console.WriteLine("Errors:\n   {0}", string.Join("\n   ", errors));

        ((IClientChannel)proxy).Close();
        factory.Close();

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}

另一种方法是在您的方案中合并这两种方法 - 使 Connect return 成为错误列表,这样您就不必单独调用来获取它们,而且您不必处理会话。