C
C#2y ago
yurah9001

❔ Asp.net API - the most reasonable in memory storage implementation

Hey guys, if you had to write asp.net web api with in memory storage - some list with items, what would be the correct way to do it? Would it be some static list or list inside a controller, or more correct way would be to register singleton to dependency container maybe also static with some locking mechanism or concurent dictionary or am I overthinking it? Searching for the correct and clean solution.
14 Replies
Sossenbinder
Sossenbinder2y ago
This is pretty much my go-to for in memory storage If you need locks etc. you can still build on top I mean, correct me if I'm wrong, but it sounds like you don't really know yet what you even need, so why not start with something simple and add according to new requirements instead of overcomplicating things upfront
yurah9001
yurah90012y ago
It could work and maybe underneath works similar from what I described, but caching is something a little bit different for me. I just need to store data for API CRUD in memory using a simple list. Not my idea, of course it is not optimal, but that is what I have to do. So I am looking for the simplest but most correct solution without using advanced components like MemoryCache. Also as I am thinking about it I would like to know the best solution for myself to better understand where I need to use statics, dependency injection, singleton and so on.
Sossenbinder
Sossenbinder2y ago
You can definitely also use a list or (in case of a cache, due to the by-key query) a dictionary. The main benefit of e.g. IMemoryCache would be that it can help you in case of memory pressure, if you use your own list or dictionary, the entries will basically linger around forever and it would be up to you to make sure you're not slowly creeping up a big memory footprint
yurah9001
yurah90012y ago
Basically simples solution, where there is only one instance for all request, sessions and concurency is not an issue.
Sossenbinder
Sossenbinder2y ago
Regarding static / singleton / dependency injection, if you want the most plain solution, you could just have a static dictionary in your controller. I usually like to use DI instead of doing things in a static fashion, since it is more easy to test and you could simply swap out the implementation from e.g. a plain Dictionary to a more sophisticated caching technology
yurah9001
yurah90012y ago
Awesome now that is where I was heading and what I wanted to hear. First thought was List inside controller, then I thought some static dictionary or singleton somewhere else, then I though maybe better solution would be concurrent dictionary and the latest idea was that I should use dependency injection and register as a singleton. What would the memory class look like then? Still a static or singleton pattern and registered as a singleton? Or am I wrong here?
Sossenbinder
Sossenbinder2y ago
public interface IDataProvider<T>
{
T? Get(string key);

void Store(string key, T data);
}

public class DataProvider<T> : IDataProvider<T>
{
private Dictionary<string, T> _provider = new();

public T? Get(string key)
{
if (!_provider.TryGetValue(key, out var val))
{
return default;
}

return val;
}

public void Store(string key, T data)
{
_provider[key] = data;
}
}
public interface IDataProvider<T>
{
T? Get(string key);

void Store(string key, T data);
}

public class DataProvider<T> : IDataProvider<T>
{
private Dictionary<string, T> _provider = new();

public T? Get(string key)
{
if (!_provider.TryGetValue(key, out var val))
{
return default;
}

return val;
}

public void Store(string key, T data)
{
_provider[key] = data;
}
}
That could be a rough outline This could then be registered in a singleton fashion for example The benefit of dependency inversion is usually that you are pretty free to "piece" together the dependencies or behaviour of a class as you want to do Is it bad to use a static field in a controller for a cache for the most simple approach? Not really. But it would definitely hurt once you start introducing dependencies you instantiate within your class, or once you want to exchange the means of how your cache works If you keep all of this strictly withing your class, you will always have to touch the code, for every change It also does not encourage reuse of code
yurah9001
yurah90012y ago
Sure I definitely agree and understand benefits of dependency injection. We got that sorted out. Which I am now curious about is concurency and one same instance for all requests, sessions. You wrote: "This could then be registered in a singleton fashion for example" I think you must register as a singleton right? Or have this used as a singleton pattern/static to be sure to have only one same instance. Concurency is the other concern I have, therefore I would use ConcurentDictionary but maybe there are better ways or should I need to take care of that?
Sossenbinder
Sossenbinder2y ago
Yep, a concurrentdictionary is a good idea if you intend to use it in e.g. a controller with potentially multiple concurrent requests And singleton binding is the only sensible option here You definitely don't want to cache data just to receive a new instance of the cache for the next request
yurah9001
yurah90012y ago
Awesome. So as I see it there are two reasonable solutions - either static/singleton class with dictionary or the component you wrote with concurent dictionary, registered as a singleton which brings all the benefits of using DI right?
Sossenbinder
Sossenbinder2y ago
Pretty much, yeah
yurah9001
yurah90012y ago
Great, thanks for helping me clarify this 🙏
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.