LINQ to SQL: Optimizing DataContext construction with the factory pattern

In the context of building out a web application, the corresponding DataContext is meant to be built out several times. The application's DataContext is constructed, some sort of data retrieval or manipulation is done, and then the DataContext goes out of scope. This operation will most likely be done several, several times throughout common user flows.

However, constructing a DataContext object is a relatively expensive operation. 99.9% of this performance hit is spent building out the MappingSource object that gets used by your DataContext. Consider that, in a stock scenario, your application goes out and builds out the MappingSource object every single time that the DataContext object is created. Typically, this is something that will happen very frequently.

These calls can be significantly optimized by caching the expensive part of the operation, which is the construction of the MappingSource object. If we wrap our DataContext construction around a factory method, we have a nice, centralized point for making this happen.

Consider the following code example:

    public static class MyDataContextFactory

    {

        private static MappingSource _myMappingSource;

        public static MyDataContext Get()

        {

            MyDataContext ctx;

            if (_myMappingSource == null)

            {

                ctx = new MyDataContext();

                _myMappingSource = ctx.Mapping.MappingSource;

            }

           else

            {

                ctx = new MyDataContext(_myMappingSource);

            }

            return ctx;

        }

    }

This example caches the MappingSource object by storing it in a static variable. We have another source file containing a partial class of MyDataContext. This partial class adds a new constructor that takes in a MappingSource object.

This partial class is used to ensure that calling code doesn't have to worry about where the connection string comes from when passing a MappingSource into the constructor of a DataContext object. Our partial class now looks something like this:

public partial class MyDataContext {     public MyDataContext(MappingSource mappingSource)         : this(Settings.Default.MyConnectionString, mappingSource)     {     } }

Now, our DataContext construction is exceptionally cheap after the first call. All subsequent calls will gain the performance advantage of the cached MappingSource object. In some informal performance testing, we found this approach to be a significant reduction in the amount of time it takes to construct a DataContext.