本文介绍了如何在 WCF 服务方法调用之间保留值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个 WCF 服务类:

I have this WCF Service 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 被定义为静态,因为我需要在调用之间保留他的值.如果我删除静态",并调用方法 Connect(创建 _conn 对象)然后调用 getErrores _conn 变量由于某种原因为空.

As you can see, _conn is defined as static, because I need to preserve his value between calls. If I remove the "static", and call method Connect (creates the _conn object) and then call getErrores _conn variable is for some reason empty.

这个问题是,如果我错过调用connect"方法,我想抛出和异常,但 _conn 仍然从上次调用中获取值.我知道我在这里做错了,但我没有看到其他选择.有什么想法吗?

The problem with this is that if I miss calling "connect" method I whant to throw and exception, but _conn stills get the value from the last call. I know i'm doing something wrong here, but I don't see another alternative. Any Ideas?

谢谢

推荐答案

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

By default, a WCF service class is instantiated for every new session that is created. For some bindings which do not support sessions, then a "session" spans only a single call, meaning that for two calls from the client (one for Connect, one for GetErrors), there will be two instances of the OhmioSVC class created, which is why if you don't specify the ConnectionBusiness property as static, two of them will be created and you will get the result you see.

您需要告诉 WCF 您要求服务合同中的会话的内容.您可以通过在服务合同声明中添加 SessionMode 属性来实现:

What you need to to tell WCF that you require a session in your service contract. You can do that by adding the SessionMode property in your service contract declaration:

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

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

If you have that, and you use a binding which does not support sessions (e.g., BasicHttpBinding), then your service will fail to open - you then need to change to a binding that supports sessions (e.g., WSHttpBinding). The code below shows an example with sessions that work:

public class StackOverflow_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 返回错误列表,这样您就不必单独调用来获取它们,并且您赢了不必处理会话.

Another alternative would be to merge the two methods in your scenario - make Connect return the list of errors, this way you don't have to make a separate call to get them, and you won't have to deal with sessions.

这篇关于如何在 WCF 服务方法调用之间保留值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-29 13:45
查看更多