Search code examples
c#dynamics-crmidisposableusing-statementxrm

How to implement a using statement when inititializing a service?


Overview:

I've came across some init code in an XRM project where the instances being initialized implement IDisposible but there is not surrounding using block on the instances.

In the examples I've looked at inside the using block there is an instance method called on the service. But in my case below the service instance are just initialized. The service methods themselves don't get called until further on in the code in private methods.

Question:

How do I use a using block for service instance initialization?

Code example 1: (Service Init)

public static void Init(string connectionString, string name)
{
    instanceName = name;
    CreateSourceServiceObjects(connectionString);
}

//Service instances just Init here no methods are called:
private static void CreateSourceServiceObjects(string connectionString)
{
    var connection = CrmConnection.Parse(connectionString);        
    sourceService = new OrganizationService(connection);
    sourceContext = new OrganizationServiceContext(sourceService);
}

//Example of where the sourceService method's are used:
public static Entity GetUserInfo(Guid userId)
{
     Entity systemuser = sourceService.Retrieve("systemuser", userId, new ColumnSet(true));
      return systemuser;
}

Code example 2: (My attempt at implementing the using statement)

private static void CreateSourceServiceObjects(string connectionString)
{
    var connection = CrmConnection.Parse(connectionString);

    //Added a Using block to auto dispose OrganizationService and OrganizationServiceContext
    using(sourceService = new OrganizationService(connection))
    using (sourceContext = new OrganizationServiceContext(sourceService))
    {
        //should there be any code in here?

    }

}

Solution

  • It looks like you have some misconception about the using statement. The using statement can only be utilized, if the code from creation to disposal of the service is scope-local.

    The situation in your question is, that the lifetime of the service object exceeds the scope, where the object is created. So your options are, to eigher redesign (create a new service object for each call to GetUserInfo) or to manage the service lifetime without help of the using statement.

    The equivalent of the using statement is described in the MSDN Reference and says, that

    using (Font font1 = new Font("Arial", 10.0f)) 
    {
        byte charset = font1.GdiCharSet;
    }
    

    is a short form for

    {
        Font font1 = new Font("Arial", 10.0f);
        try
        {
            byte charset = font1.GdiCharSet;
        }
        finally
        {
            if (font1 != null)
                ((IDisposable)font1).Dispose();
        }
    }
    

    Normally, implementing the class with IDisposable would be the way. However, in your case, you have static methods and static variables. So the first question would be, what do you expect to be the service lifetime? The default answer for static variables would be: "as long as the application is running" and then it becomes clear, what you have to do in order to ensure proper cleanup:

    • If CreateSourceServiceObjects is called more than once, eigher ensure disposal of the old service object before reassignment or reject the re-initialization
    • Depending on your program type, hook into the application exit and manually dispose the service object, if it is assigned

    I want to point out, that you can win a lot here, by redesigning your class to be non-static. With an instance of your class, you could just go with the standard IDisposable pattern, which is probably safer than some custom program exit cleanup code.

    Having said all that, IF your service has a proper implementation of dispose and finalize functionality, you don't need to worry about disposing at all, since your static object would just live till the application exits and then free unmanaged resources through the finalizer.