Using instances and singlets in WCF web service with high concurrency

I am developing a WCF web service that returns information from one of several databases based on string providerCode .

At the highest level, the service calls the StaticBroker class, which checks providerCode and returns the corresponding subclass of DataManager , say MyDataManager . The service then calls MyDataManager.getVehicleFetcherForStop() , which returns an instance of the VehicleInfoFetcher class, which is used to retrieve information.

I am completely new to all of this, and I think that I could fix it incorrectly. Here is the code for how I am doing this 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 from StaticBroker that stores only one instance of each type of DataManager . Finally, an actual instance of the class is created inside the DataManager that does the real work, SomeVehicleFetcher .

Is this a smart way to do this? Or can these singletones and shared instances cause problems while using the web service? I was worried that creating a ton of new instances could lead to memory problems. As you can see, I really don't understand how the application life cycle / memory cycle works in a web service.

+4
source share
1 answer

You are trying to solve a hypothetical problem ("may lead to memory problems") with a design that is not convinced of the correctness or necessity. In addition, ADO.NET has a ton of optimizations that handle database connection performance.

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

See section 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 eliminates the need for a Broker.

In addition, the class you call β€œBroker” is more like Factory, and factories fell out of dislike because they allow you to point dependency injection down in the weeds rather than up, and they create a configuration environment for unit testing a complex enterprise .

Of course, there can be a lot more than what differs from the tastes of the DataManager than you showed. If so, and they cannot be centralized, I recommend that you explore one of the many Inversion Of Control containers that are available (AutoFac, Unity, Castle Windsor come to mind). These containers will support the logic with which the flavor of DataManager should be based on the value of the execution time of the provider code at the very top.

+3
source

Source: https://habr.com/ru/post/1494758/


All Articles