Search code examples
c#asp.net-mvcusing

When consuming a WCF service, is it good form to return from within a using statement?


I have a WCF service that I am consuming, and have been doing well so far.

However on our production system with a lot of traffic, I am noticing that that after gradual consistent rise and falls in memory (time in between gradually elongates and the delta gradually increases), the memory consumption is trending higher.

I'm wondering if it could be due to the way I am consuming the DAL web service:

For example:

    public static int GetUserTypeFromProfileID(int profileID)
    {
        try
        {
            memberServiceClient = new MemberServiceClient();                                // connect to the data service
            return memberServiceClient.GetUserTypeFromProfileID(profileID);                 // get the profileID associated with the sessionID
        }
        catch (Exception ex)
        {
            ErrorLogging.Instance.Fatal(ex);
            return 0;
        }
    }

If I changed this to the following, using a using statement:

    public static int GetProfileIDFromSessionID(string sessionID)
    {
        try
        {
            using (memberServiceClient = new MemberServiceClient())                                // connect to the data service
            {
                return memberServiceClient.GetProfileIDFromSessionID(sessionID);                // get the profileID associated with the sessionID
            }

        }
        catch (Exception ex)
        {
            ErrorLogging.Instance.Fatal(ex);
            return 0;
        }
    }

Is it good form to perform the return inside the using section?


Solution

  • I believe there is nothing specific to WCF with using statement. It will dispose your MemberServiceClient before returning the value.

    However Dispose() method on a WCF service client calls Close() method inside, which can throw exceptions. So it's better to call Close() method directly. You should also call Abort() method when exceptions occur. Here's the recommended implementation.

    var result;
    try
    {
        memberServiceClient = new MemberServiceClient();
        result = memberServiceClient.GetUserTypeFromProfileID(profileID);
        memberServiceClient.Close();
    }
    catch (FaultException e)
    {
        //handle exception
        memberServiceClient.Abort();
    }
    catch (CommunicationException e)
    {
        //handle exception
        memberServiceClient.Abort();
    }
    catch (TimeoutException e)
    {
        //handle exception
        memberServiceClient.Abort();
    }
    

    Note: I have written a simple base class that handles these details. It's on NuGet.

    Update:

    Here's an example with WcfClientBase as requested:

    public class MemberServiceManager : ServiceClientBase<MemberServiceClient>
    {
        public int GetUserTypeFromProfileID(int profileID)
        {
            //makes a call to GetUserTypeFromProfileID operation, closes the channel and handles the exceptions
            //you may want to implement another base class for overriding exception handling methods
            //return value will be default of return type if any exceptions occur
            return PerformServiceOperation(item => item.GetUserTypeFromProfileID(profileID));
        }
    
        //or you can manually check if any exceptions occured with this overload
        public bool TryGetUserTypeFromProfileID(int profileID, out int userType)
        {
            return TryPerformServiceOperation(item => item.GetUserTypeFromProfileID(profileID), out userType);
        }
    
    
        //these exception handling methods should be overriden in another common subclass
        //they re-throw exceptions by default
        protected override void HandleCommunicationException(CommunicationException exception)
        {
            Console.WriteLine(exception.Message);
        }
    
        protected override void HandleFaultException(FaultException exception)
        {
            Console.WriteLine(exception.Message);
        }
    
        protected override void HandleTimeoutException(TimeoutException exception)
        {
            Console.WriteLine(exception.Message);
        }
    
    }
    

    You can also take a look at the source code on GitHub