// *******************************Uncomment this method and comment out the other to implement AppFabric caching for market summary /* /// <summary> /// Gets the current market summary. This results in an expensive DB query in the DAL; hence look to cache data returned for 60 second or so. /// </summary> public MarketSummaryDataModelWS getMarketSummary() { // ============ To use WINDOWS SERVER App Fabric Caching (on-premise only): uncomment at top of page 'using Microsoft.ApplicationServer.Caching;' // Add references to the host program (TradeWebBSL, BusinessServiceHost, BusinessServiceConsole and/or BusinessServiceNTServiceHost project(s): // \stocktrader\sharedlibraries\winserverappfabric\*.dll (all assemblies in this directory). // Add reference to: \stocktrader\sharedlibraries\configuration\ConfigService.WinServerAppFabricUtility.dll // // ============ To use WINDOWS AZURE App Fabric Caching (on-premise or on-azure): uncomment at top of page 'using Microsoft.ApplicationServer.Caching;' // Add references to the host program (TradeWebBSL, BusinessServiceHost, BusinessServiceConsole and/or BusinessServiceNTServiceHost project(s): // \stocktrader\sharedlibraries\winazureappfabric\*.dll (all assemblies in this directory). // Add reference to: \stocktrader\sharedlibraries\configuration\ConfigService.AzureAppFabricConfigUtility.dll //This is an example of using ConfigService distributed cache utility to access a Win Server or Win Azure AppFabric cache //without any cache config info embedded in config. The utility returns a pre-tuned client, already connected to the //distributed cache so its high performance. First, you must find the cache you want from the Settings.connectedCaches list. //This list is automatically created based on using ConfigWeb inherited settings to specified connected_caches. //Note, your app may use as many different caches (namespaces on Azure, or named caches on Win Server) as you want. //Just add more keys to ConfigSettings (currently, keys are defined for up to three different caches from a single app. //Also note below, on Azure AppFabric, there is only one named cache 'default'; but you can create many different namespaces, //hence, many different caches (they will all just be named 'default', but the different namespaces mean they reside om //different servers (and maybe different geographic regions, depending on how you setup the App Fabric cache namespace(s). //At any rate, StockTrader as an app does not present a lot of opportunity to use a cache, since most information should not be //stale to the user. However, market summary is an exception--who cares if updated only every 30 seconds or so? Plus, its an //expensive query. The below code is for example only. Yo can also use ASP.NET local output caching from the Web app to cache the //results of the call to this method (or, put in a distributed cache the StockTrader Web app uses. But, it is useful to //also cache the data here on the Web Service tier itself; since other clients may be calling this method a lot, putting stress //on the database. //The differnce between using a local ASP.NET cache vs. a AppFabric distributed cache is one makes sure all nodes/instances in a scale-out //cluster are using/presenting the exact same data; local .NET caching means nodes will be out of sync. So it depends on the data //and the scenario on when to use a distributed cache vs. a node-local cache. You can never use a local cache for session data //in a scale-out scenario: the nodes must be using the same cache. //Finally, most of the logic below to use the Config Service cache utility could be put into a re-usable method, if an app was going to use the utility in lots of places. MarketSummaryDataModelWS returnData=null; DistributedCaches myStockTraderMktSummaryCache=null; DataCache theCache =null; //First we need to find the actual cache we are interested in using, the service domain might be using many //different caches, potentially on different servers/azure namespaces. We will look up by name. However, //we really should look up by name and Azure namespace, since all Azure AppFabric caches are named 'default.' (as //of this writing. On-premise, Win Server AppFabric clusters can have named caches with different names/properties. if (Settings.connectedCaches!=null) myStockTraderMktSummaryCache = Settings.connectedCaches.Find(delegate (DistributedCaches cacheExists) {return cacheExists.Name.ToLower().Equals("default");}); //Ok, if we have it, keep going. If you have not setup a distributed cache, the logic below simply gets it from the DB //on every call. if (myStockTraderMktSummaryCache!=null) { //If using the ConfigServer pre-tuned DistributedCacheUtility, make sure to put the getDataCache call in a try-catch, //and call closeDataCache on an exception. An exception can happen if for any reason the //cache connection from the client was broken. The closeDataCache method ensure the cache is //disposed of, a new factory created and new connection established on any subsequent calls. try { theCache = (DataCache)DistributedCacheUtility.getDataCache(myStockTraderMktSummaryCache, false, new Settings()); returnData = (MarketSummaryDataModelWS)theCache.Get("mktSummary"); } catch { DistributedCacheUtility.closeDataCache(myStockTraderMktSummaryCache, new Settings()); } } //Ok, it was either not in the cache, or the cache was offline--so we must go get it from the DB. And then stuff //it into the cache so next caller does not have to goto the DB. if (returnData == null) { dalMarketSummary = Trade.DALFactory.MarketSummary.Create(Settings.DAL); dalMarketSummary.Open(Settings.TRADEDB_SQL_CONN_STRING); try { returnData = dalMarketSummary.getMarketSummaryData(); if (theCache != null && returnData!=null) try { theCache.Put("mktSummary", returnData, new TimeSpan(0,0,60)); } catch (Exception ePut) { ConfigUtility.writeConfigConsoleMessage("Warning: a cache put operation failed.\n\n" + ePut.ToString(), System.Diagnostics.EventLogEntryType.Warning, true, new Settings()); } } catch { throw; } finally { dalMarketSummary.Close(); } } return returnData; } * */ /// <summary> /// Gets a single quote based on symbol. /// </summary> /// <param name="symbol">Symbol to get data for.</param> public QuoteDataModel getQuote(string symbol) { dalMarketSummary = Trade.DALFactory.MarketSummary.Create(Settings.DAL); dalMarketSummary.Open(Settings.TRADEDB_SQL_CONN_STRING); try { return dalMarketSummary.getQuote(symbol); } catch { throw; } finally { dalMarketSummary.Close(); } }
/// <summary> /// Gets a quotes based on symbols string. /// </summary> /// <param name="symbol">Symbol to get data for.</param> public List<QuoteDataModel> getQuotes(string symbols) { dalMarketSummary = Trade.DALFactory.MarketSummary.Create(Settings.DAL); dalMarketSummary.Open(Settings.TRADEDB_SQL_CONN_STRING); try { string[] quotes = symbols.Split(new char[] { ' ', ',', ';' }); List<QuoteDataModel> quoteList = new List<QuoteDataModel>(); foreach (string quote in quotes) { string stringquotetrim = quote.Trim(); if (!stringquotetrim.Equals("")) { QuoteDataModel quoteData = dalMarketSummary.getQuote(stringquotetrim); if (quoteData != null) { quoteList.Add(quoteData); } } } return quoteList; } catch { throw; } finally { dalMarketSummary.Close(); } }
/// <summary> /// Gets the current market summary. This results in an expensive DB query in the DAL; hence look to cache data returned for 60 second or so. /// </summary> public MarketSummaryDataModelWS getMarketSummary() { MarketSummaryDataModelWS returnData=null; dalMarketSummary = Trade.DALFactory.MarketSummary.Create(Settings.DAL); dalMarketSummary.Open(Settings.TRADEDB_SQL_CONN_STRING); try { returnData = dalMarketSummary.getMarketSummaryData(); } catch { throw; } finally { dalMarketSummary.Close(); } return returnData; }