System.Web.Services.WebService - Is it possible to isolate the service per client

青春壹個敷衍的年華 提交于 2019-12-11 14:48:44

问题


I have an legacy System.Web.Services.WebService (not WCF) that I have to maintain.

Ocassionly I run into some wired behaviours that I would describe as race conditions.

  • Either the service hangs and has to be restarted.

  • Sometimes I get this exception:

    System.NotSupportedException: Multiple simultaneous connections
    or connections with different connection strings inside the same 
    transaction are not currently supported.
        at MySql.Data.MySqlClient.MySqlConnection.Open()
        ...
    

I know whats the root cause. The service utilizes a lib that talks to mysql and was not designed with webservices in mind. Unfortunatly I cannot change this lib.

One example webmethod looks like this:

[WebMethod(EnableSession = true)]
public void DoSomething()
{
    var login = this.Session["login"] as LoginDetails;
    ExternalLib.SetLoginData(login.Schema, login.User, login.Pass);

    ExternalLib.PerformTask();

}

So the problem here is this:

  • ExternalLib.SetLoginData just set's some global vars
  • ExternalLib.PerformTask performs database calls, some inside a transaction.
  • The process is like 1. Create MySqlConnection or take it from cache 2. Create MySqlCommand 3. Execute Command 4. Dispose command

Client a) calls DoSomething() and I init his connection. Half way done with his job Client b) calls DoSomething() which apparently changes the Login-Data for client a and the next call inside the transaction will use the login from client b) which causes the transaction.

Anyway, I know this is a bad design but my question is how to workaround this. Currently (since I only have 10 clients) I created a dedicated Website on a differnet port which all point to the same root directory but this is an akward solution.

Maybe there is a possibility to run every session inside its on realm. Any suggestions. If I understand this page correctly for WCF is is the default behaviour: http://msdn.microsoft.com/en-us/magazine/cc163590.aspx

Per-Call Services
Per-call services are the Windows Communication Foundation default instantiation mode. When the service type is configured for per-call activation, a service instance, a common language runtime (CLR) object, exists only while a client call is in progress. Every client request gets a new dedicated service instance.


回答1:


Seeing as this is probably a threading issue you can lock the ExternalLib to prevent separate instances from calling the code.

public class ExtenalLibWrapper
{
    private static object Locker = new object();

    public void DoSomething(LoginDetails details)
    {
        lock(Locker)
        {
            ExternalLib.SetLoginData(login.Schema, login.User, login.pass);
            ExternalLib.PerformTask();
        }
    }
}



回答2:


I already wrapped all my public methods in a neat execute wrapper to provide global exception logging.

This forces my webservice to process one request after another, but like I mentioned, the max. number of simultanious clients is 10

public class MyService : System.Web.Services.WebService
{

    [WebMethod(EnableSession = true)]
    public static int Add(int value1, int value2)
    {
        return Execute(() =>
        {
            var calculator = new Calculator();
            return calculator.Add(value1, value2);
        });
    }

    private static Logger logger =
        LogManager.GetLogger(typeof(MyService).Name);
    private static System.Threading.SemaphoreSlim ss =
        new System.Threading.SemaphoreSlim(1, 1);

    private void Execute(Action method)
    {
        ss.Wait();
        try { method.Invoke(); }
        catch (Exception ex)
        {
            logger.FatalException(method.Method + " failed", ex); throw; 
        }
        finally { ss.Release(); }
    }

    private T Execute<T>(Func<T> method)
    {
        ss.Wait();
        try { return method.Invoke(); }
        catch (Exception ex)
        {
            logger.FatalException(method.Method + " failed", ex); throw; 
        }
        finally
        {
            ss.Release();
        }
    }
}


来源:https://stackoverflow.com/questions/17044555/system-web-services-webservice-is-it-possible-to-isolate-the-service-per-clien

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!