Given that I have the following WCF service:
class LookUpService
{
public List<County> GetCounties(string state)
{
var db = new LookUpRepository();
return db.GetCounties(state);
}
}
class County
{
public string StateCode{get;set;}
public string CountyName{get;set;}
public int CountyCode{get;set;}
}
What will be the most efficient (or best) way to cache a state's counties using weak references (or any other approach) so that we don't hit the database every time we need to look up data.
Note that we will not have access to the HttpRuntime (and HttpContext).
For this scenario you're going to want to use a WeakReference style hash table of sorts. None is available in the BCL (until 4.0) but there are several available online. I will be using the following for this sample
http://blogs.msdn.com/jaredpar/archive/2009/03/03/building-a-weakreference-hashtable.aspx
Try the following cdoe
class LookupService {
private WeakHashtable<string,List<Count>> _map = new WeakHashtable<string,List<County>>();
public List<County> GetCounties(string state) {
List<Count> found;
if ( !_map.TryGetValue(state, out found)) {
var db = new LookUpRepository();
found = db.GetCounties(state);
_map.Add(state,found);
}
return found;
}
}
As you can see, it's not much different than using a normal Dictionary<TKey,TValue>
Why do you not have acccess to HttpRuntime? You don't need the context. You only need the class.
You can use System.Web.Caching in a non-ASP.NET app, without using the HttpContext.
see also Caching in WCF?
Related
I need to get a list of stations(lazily) from a remote service and to store it in DB and in memory.
Then, if someone wants the list, he tries to read the in memory list.
If it's null , it goes to Db and if there's no data in DB , it should go to a remote service , fetch the list , and to store the list in DB and in memory.
(Basically, I don't want to go to the remote service every request)
So I've used the .net core's singleton service :
services.AddSingleton<IStations,Stations>()
Where the class will contain the list itself :
public class Stations:IStations
{
public List<StationModel> LstStationModel
{
get
{
lock (locker)
{
if (_lstStationModel == null)
{
var ls = GetStationsFromDb().Result;
if (ls!=null && ls.Count > 0)
_lstStationModel = ls;
else
_lstStationModel = GetStationsFromProvider().Result;
}
return _lstStationModel;
}
}
set
{
lock (locker)
{
_lstStationModel = value;
}
}
}
}
So now I have a single property in a singleton class .
When someone asks for the list , I check if it's null , then I go to db.
If the db doesn't have the data , I start fetching from remote and fill the list.
I've also added lock , so that 2 requests won't invoke fetching twice.
Question
Something here doesn't look right.I'm not sure it's the right way of dong it. And besides , I really don't like this solution.
Is there any way to do it in a more elegant/better way ?
You could use Lazy for that intent. If you pass true in the constructor it indicates it is thread-safe.
Example:
public class Stations : IStations
{
Lazy<List<StationModel>> _lazyStation = new Lazy<List<StationModel>>(() => Provider.GetStationsFromProvider().Result, isThreadSafe: true);
public List<StationModel> LstStationModel
{
get { return _lazyStation.Value; }
set { _lazyStation = new Lazy<List<StationModel>>(() => value, isThreadSafe: true); }
}
}
Note that this wouldn't be the best solution for caching or accessing data because you are coupling your Provider to the Stations object. I'd recommend creating a service/class and inject your "Provider" (as an abstraction) into it in order to invert the dependency (Dependency Inversion Principle). If you will create a Service/Manager class you could even inject a ICacheService and implement it using MemoryCache
This is actually 2 questions in one.
I have an asp.net mvc application where I have to load a list of Modules, its just a simple list with ID, modulename and a class name to render it on the view with font awesome.
My model is like this:
public class Module
{
[Key]
public int Id { get; set; }
public string ModuleName { get; set; }
public string FontAwesomeClass { get; set; }
}
Because the module list is a Partial View that will render some icons on the top navigation bar, I dont want that for each refresh of the app, it goes to the DB, so it must be cached(I am using Azure REDIS Cache, not relevant for the question anyway), so instead of calling the DB context directly from the controller, I am calling a Cache Class that will check if the cache object exists, if not it will retrieve it from DB, if it does, it will return it from cache.
This my solution structure:
http://screencast.com/t/uayPYiHaPCav
Here is my controller Module.cs
public ActionResult GetModules()
{
return View(Cache.Module.GetModules());
}
As you can see the Controller does not have any logic where to get the data from.
Here is the Module.cs (on the Cache Namespace)
public class Module
{
private AppDataContext dbApp = new AppDataContext();
//Load modules from cache or from database
public static List<Models.Module> GetModules()
{
IDatabase cache = Helper.Connection.GetDatabase();
List<Models.Module> listOfModules = (List<Models.Module>)cache.Get("Modules");
if (listOfModules == null)
{
return dbApp.ModuleList.ToList();
}
else
{
return listOfModules;
}
}
}
Here I have a compiler error which I am not sure how to best fix it:
Error CS0120 An object reference is required for the non-static field,
method, or property 'Module.dbApp'
So that was my first question.
The 2nd question is more about the design pattern, do you consider this correct or not? the way I am trying to get the data from Cache, and its actually the Cache class which checks if data is on it or if it has to go to the DB.
First Question: make your private member static
private static AppDataContext dbApp = new AppDataContext();
2nd Question: your cache strategy seems pretty standard. The only thing is that you might want to expire cache data. For example, the cached data can get old and the longer it stays in the cache the older it gets. You might at some point want to expire it and get fresh data again.
Update:
#EstebanV for code sample (this off the top of my head, don't assume that it compiles):
/**
ICachedPersonDao abstracts away the caching mechanism
away from the core of your application
**/
public CachedPersonDao : ICachedPersonDao
{
private IPersonDao personDao = null;
public CachedPersonDao(IPersonDao personDao)
{
this.personDao = personDao;
}
public Person GetPersonById(int id){
bool isInCache = CACHE.SomeFunctionThatChecksInYourCache(id);
if (isInCache)
{
return CACHE.SomeFunctionThatReturnsTheCachedPerson(id);
}
else
{
//Well it's not in the cache so let's get it from the DB.
return this.personDao.GetPersonById(id);
}
}
}
/**
IPersonDao abstracts database communication
away from the core of your application
**/
public class PersonDao : IPersonDao
{
public Person GetPersonById(int id)
{
/** Get the person by id from the DB
through EntityFramework or whatever
**/
}
}
Usage:
In your controller, use ICachedPersonDao if you want to attempt to get from cache or use IPersonDao if you want to get it directly from the database without checking the cache.
Like I said, you should learn Dependency Injection it will help "inject" these dependencies into the classes that uses them.
I say again, this is off the top of my head. It won't compile. It's just to illustrate the concept.
Recently we learned about AppDomain Recycling of IIS and how it affects static variables setting them to their primary values (nulls, 0s, etc).
We use some static variables that are initialized in a static constructor (for first time initialization, configuration values like "number of decimal places", "administrator email", etc... that are retrieved from DB) and then only read their value along the website execution.
Whats the best way of solving this problem? Some possible ideas:
Checking if variable is null/0 at each retrieval (don't like it because of a possible performance impact + time spent to add this check to each variable + code overload added to the project)
Somehow preventing AppDomain Recycling (this reset logic doesn't happen in Windows forms with static variables, shouldn't it work similarly as being the same language in both environments? At least in terms of standards as static variables management)
Using some other way of holding these variables (but we think that for being some values used for info as global reference for all users, static variables were the best option performance/coding wise)
Subscribing to an event that is triggered in those AppDomain Recycling so we can reinitialize all those variables (maybe best option if recycling can't be prevented...)
Ideas?
I would go with the approach that you don't like.
Checking if variable is null/0 at each retrieval (don't like it because of a possible performance impact + time spent to add this check to each variable + code overload added to the project)
I think it's faster than retireving from web.config.
You get a typed object
Its not a performance impact as you are not going to database on every retrieval request. You'll go to database (or any source) only when you find that current value set to its default value.
Checking the null wrapped into code:
public interface IMyConfig {
string Var1 { get; }
string Var2 { get; }
}
public class MyConfig : IMyConfig {
private string _Var1;
private string _Var2;
public string Var1 { get { return _Var1; } }
public string Var2 { get { return _Var2; } }
private static object s_SyncRoot = new object();
private static IMyConfig s_Instance;
private MyConfig() {
// load _Var1, _Var2 variables from db here
}
public static IMyConfig Instance {
get {
if (s_Instance != null) {
return s_Instance;
}
lock (s_SyncRoot) {
s_Instance = new MyConfig();
}
return s_Instance;
}
}
}
Is there any reason why you can't store these values in your web.config file and use ConfiguationManager.AppSettings to retrieve them?
ConfigurationManager.AppSettings["MySetting"] ?? "defaultvalue";
In view of your edit, why not cache the required values when they're first retrieved?
var val = HttpContext.Cache["MySetting"];
if (val == null)
{
val = // Database retrieval logic
HttpContext.Cache["MySetting"] = val;
}
It sounds like you need a write-through (or write-behind) cache, which can be done with static variables.
Whenever a user changes the value, write it back to the database. Then, whenever the AppPool is recycled (which is a normal occurrence and shouldn't be avoided), the static constructors can read the current values from the database.
One thing you'll have to consider: If you ever scale out to a web farm, you'll need to have some sort of "trigger" when a shared variable changes so the other servers on the farm can know to retrieve the new values from the server.
Comments on other parts of your question:
(don't like [Checking if variable is null/0 at each retrieval] because of a possible performance impact + time spent to add this check to each variable + code overload added to the project
If you use a write-through cache you won't need this, but in either case The time spent to check a static variable for 0 or null should be negligible.
[AppDomain recycling] doesn't happen in Windows forms with static variables, shouldn't it work similarly as being the same language in both environments?
No, WebForms and WinForms are completely different platforms with different operating models. Web sites should be able to respond to many (up to millions) of concurrent users. WinForms are built for single-user access.
've resolved this kind of issue, following a pattern similar to this. This enabled me to cater for handling circumstances where the data could change. I set up my ISiteSettingRepository in the bootstrapper. In 1 application I get the configuration from an XML file but in others I get it from the database, as and when I need it.
public class ApplicationSettings
{
public ApplicationSettings()
{
}
public ApplicationSettings(ApplicationSettings settings)
{
ApplicationName = settings.ApplicationName;
EncryptionAlgorithm = settings.EncryptionAlgorithm;
EncryptionKey = settings.EncryptionKey;
HashAlgorithm = settings.HashAlgorithm;
HashKey = settings.HashKey;
Duration = settings.Duration;
BaseUrl = settings.BaseUrl;
Id = settings.Id;
}
public string ApplicationName { get; set; }
public string EncryptionAlgorithm { get; set; }
public string EncryptionKey { get; set; }
public string HashAlgorithm { get; set; }
public string HashKey { get; set; }
public int Duration { get; set; }
public string BaseUrl { get; set; }
public Guid Id { get; set; }
}
Then a "Service" Interface to
public interface IApplicaitonSettingsService
{
ApplicationSettings Get();
}
public class ApplicationSettingsService : IApplicaitonSettingsService
{
private readonly ISiteSettingRepository _repository;
public ApplicationSettingsService(ISiteSettingRepository repository)
{
_repository = repository;
}
public ApplicationSettings Get()
{
SiteSetting setting = _repository.GetAll();
return setting;
}
}
I would take a totally different approach, one that doesn't involve anything static.
First create a class to strongly-type the configuration settings you're after:
public class MyConfig
{
int DecimalPlaces { get; set; }
string AdministratorEmail { get; set; }
//...
}
Then abstract away the persistence layer by creating some repository:
public interface IMyConfigRepository
{
MyConfig Load();
void Save(MyConfig settings);
}
The classes that can read and write these settings can then statically declare that they depend on an implementation of this repository:
public class SomeClass
{
private readonly IMyConfigRepository _repo;
public MyClass(IMyConfigRepository repo)
{
_repo = repo;
}
public void DoSomethingThatNeedsTheConfigSettings()
{
var settings = _repo.Load();
//...
}
}
Now implement the repository interface the way you want (today you want the settings in a database, tomorrow might be serializing to a .xml file, and next year using a cloud service) and the config interface as you need it.
And you're set: all you need now is a way to bind the interface to its implementation. Here's a Ninject example (written in a NinjectModule-derived class' Load method override):
Bind<IMyConfigRepository>().To<MyConfigSqlRepository>();
Then, you can just swap the implementation for a MyConfigCloudRepository or a MyConfigXmlRepository implementation when/if you ever need one.
Being an asp.net application, just make sure you wire up those dependencies in your Global.asax file (at app start-up), and then any class that has a IMyConfigRepository constructor parameter will be injected with a MyConfigSqlRepository which will give you MyConfigImplementation objects that you can load and save as you please.
If you're not using an IoC container, then you would just new up the MyConfigSqlRepository at app start-up, and manually inject the instance into the constructors of the types that need it.
The only thing with this approach, is that if you don't already have a DependencyInjection-friendly app structure, it might mean extensive refactoring - to decouple objects and eliminate the newing up of dependencies, making unit tests much easier to get focused on a single aspect, and much easier to mock-up the dependencies... among other advantages.
So far, I've tried the following:
public class Widget
{
public int Id;
public string Name;
}
public static class Main
{
public static void Main()
{
// Initialize store and preload with widgets...
using (var session = store.OpenSession())
{
var widgets = session.Load<Widget>();
foreach(var widget in widgets)
{
Console.WriteLine(widget.Name);
}
}
}
}
I have been able to load all by adding an index and then using that index as a query:
var store = new DocumentStore();
store.DatabaseCommands.PutIndex("AllWidgets", new IndexDefinition<Widget>
{
Map = widget => from widget in widgets
select new { widget }
});
// Back in Main
var widgets = session.Query<Widget>("AllWidgets");
// Do stuff with widgets.
Is there a way to just get all documents of type Widget without having to create an index?
At this point I'm just playing with RavenDB in a sandbox environment. I realize that this is usually not the best approach to fetching data.
Yes
use the DocumentsByName query - this as far as I can work out is not intuitive in the client interface at the moment, but looks something like this:
documentSession.LuceneQuery<ImageDocument>("Raven/DocumentsByEntityName")
.Where("Tag:Widgets")
.Take(100)
.ToArray();
It helps if you know the HTTP API sometimes :)
NB: Note how it pluralises for you, this is a convention and can be overridden.
Note: In the unstable fork (so likely to be stable soon, the above can easily be achieved with
documentSession.Query<ImageDocument>().Take(100).ToArray()
Much nicer
I am creating a portal where many sites will run of the same MVC application. I have a list of Sites stored in the HttpRuntime.Cache. Is it wrong to access the cache via a static method? Should I instead be passing this on view data?
For example, is this wrong on the view:
Where the code for SiteHelper is:
public class SiteHelper {
private static object #lock = new object();
private const string siteKey = "FelixSites";
public static Site CurrentSite {
get {
var context = HttpContext.Current.Wrap();
var sites = context.Cache[siteKey] as Site[];
if (sites == null) {
lock (#lock) {
if (sites == null) {
sites = SiteService.GetSites();
context.Cache[siteKey] = sites;
}
}
}
return sites.Single(s => s.Domain == context.Request.UrlReferrer.AbsoluteUri);
}
}
}
The only reason it may be bad to use the static property is that breaks the separation of concerns between your view and your model. The model should be the only one concerned with how the data is retrieved - even from objects that are in the same application domain.
While it may seem like overkill to present this data to the view via ViewData it really is the best practice as it preserves the separation of concerns. The more you actively preserve this separation, the better your application will handle refactoring and bug fixes down the road.