Using instances and singletons in a high concurrency WCF web service

.net-4.5, c#, singleton, wcf, web-services

Solution

You are trying to solve a hypothetical problem ("might lead to memory issues") with a design that you are not convinced is correct or is needed. Plus, ADO.NET has a ton of optimizations that handle database connection performance.

This is just creating more work and more testing headaches (how will you isolate code that depends on this broker?).

See Anti-patterns:

Premature Optimization, Not Invented Here

EDIT:

public interface IVehicleInfoRetriever {
    VehicleInfoResponse getVehicleInfo(string primaryCode);
}

public class DataManager<TVehicleInfoFetcher> 
    where TVehicleInfoFetcher : class, new(), IVehicleInfoRetriever 
{

    private string _providerCode;

    public DataManager() : this("UK") { }

    public DataManager(string providerCode) {
        _providerCode = providerCode;
    }

    public string getUpcomingVehicleInfoNow(string stopID)
    {
        VehicleInfoFetcher infoFetcher;
        if ( shouldCheckDB(stopID))
            VehicleInfoFetcher infoFetcher = new DatabaseVehicleInfoFetcher(_providerCode);
        else 
            fetcher = new TVehicleInfoFetcher();

            return fetcher.getVehicleInfo(primaryCode).Result;  // This is an async method, but we wait for the result
        }
    }

}

Something like this removes the need for the 'Broker'.

Also, the class that you are calling 'Broker' is more of a Factory and factories have fallen out of favor because they allow dependency injection to be specified way down in the weeds instead of at the top and they make environment configuration for unit testing a complex undertaking.

Of course, there might be a lot more that is different between the flavors of DataManager than you have shown. If this is the case and they cannot be centralized, then I recommend that you investigate one of the many Inversion Of Control containers that are available (AutoFac, Unity, Castle Windsor come to mind). These containers will keep the logic of which flavor DataManager to use based on the runtime value of provider code at the very top.

Problem

I am developing a WCF web service that return information from one of several databases based upon `string providerCode`. At the very highest level, the service calls a `StaticBroker` class, which inspects `providerCode` and returns an appropriate subclass of `DataManager`, let's say `MyDataManager`. The service then calls `MyDataManager.getVehicleFetcherForStop()` which returns an instance of class `VehicleInfoFetcher`, which is used to obtain the info. I'm quite new to all this, and I think I might have architected it wrong. Here's the code for how I do it right now (simplified): Service.svc.cs ``` // Public-facing web service method public string getRealtimeInfo(String stopID, string providerCode = "UK") { DataManager dm = StaticBroker.Instance.dataManager(stopID); return dm.getUpcomingVehicleInfoNow(primaryCode); } ``` StaticBroker ``` public sealed class StaticBroker { UKDataManager ukDataManager = null; // Create one instance of each data manager when the Web Service is started, // to save memory private StaticBroker() { ukDataManager = new UKDataManager(); } public DataManager dataManager(string providerCode) { if (providerCode.Equals(UKDataManager.DEFAULT_PROVIDER_CODE)) return ukDataManager; // else if... } // Most singleton stuff snipped out private static readonly StaticBroker instance = new StaticBroker(); } ``` UKDataManager ``` public class UKDataManager : DataManager { public const string DEFAULT_PROVIDER_CODE = "UK"; public string getUpcomingVehicleInfoNow(string stopID) { VehicleInfoFetcher infoFetcher; if ( shouldCheckDB(stopID)) VehicleInfoFetcher infoFetcher = new DatabaseVehicleInfoFetcher("UK"); else fetcher = new UKLiveVehicleInfoFetcher(); return fetcher.getVehicleInfo(primaryCode).Result; // This is an async method, but we wait for the result } } } ``` As you can see, I have a Singleton of `StaticBroker`, which itself stores just one instance of each type of `DataManager`. Finally, within the DataManagers, an actual instance is created of the class that does the real work, `SomeVehicleFetcher`. Is this a sensible way of doing it? Or are these Singletons and shared instances going to lead to problems when there is high concurrent usage of the web service? I was worried that creating a ton of new instances might lead to memory issues. As you can see, I don't really understand how an App's lifetime/memory cycle works in a Web Service.

Original source