Multiple MemoryCache in ASp .Net Core Web API - asp.net-core

I have an ASP .Net Core 2.2. Web API. I'd like to speed up performance by using MemoryCache. However, I need to cache 2 different types, both which use integer keys. The one type is a list of users and the other is a list of groups.
Now, I'm adding the MemoryCache service in the Startup.cs file:
services.AddMemoryCache();
and then I'm using dependency injection to access this cache in two different places (in Middleware and in a service I wrote).
From what I understand, both these caches are the same instance. So when I add my various users and groups to it, since they both have integer keys, there will be conflicts. How can I handle this? I thought about using two caches - one for each type - but (a) I'm not sure how to do this and (b) I've read somewhere that it's not recommended to use multiple caches. Any ideas?

Yeah, I've had the same issue before and resorted to creating an extended version of the MemoryCache that allows me to plug in different "stores".. You can do it simply by wrapping the data you're sticking into the cache in a "metadata" type class. I suppose similar to how the ServiceDescriptors wrap your service registrations in the DI?
Also, in specific answer to the point "I thought about using two caches - one for each type". This is where the problem will arise because I believe IMemoryCache gets registered as a singleton by default

I ran into this problem myself. One solution I thought of was to just two instantiate separate memory caches in a wrapper class and register the wrapper class as a singleton instance. However, this only makes sense if you have different requirements for each memory cache and/or you expect to store a massive amount of data for each memory cache (at that point, an in-memory cache may not be what you want).
Here is some example classes I want to cache.
// If using a record, GetHashCode is already implemented through each member already
public record Person(string Name);
// If using a class, ensure that Equals/GetHashCode is overridden
public class Car
{
public string Model { get; }
public Car(string model)
{
Model = model;
}
public override bool Equals(object? obj)
{
return obj is Car car &&
Model == car.Model;
}
public override int GetHashCode()
{
return HashCode.Combine(Model);
}
}
Here is a dual MemoryCache implementation.
public class CustomCache : ICustomCache // Expose what you need and register it as singleton instance
{
private readonly MemoryCache personCache;
private readonly MemoryCache carCache;
public CustomCache(IOptions<MemoryCacheOptions> personCacheOptions, IOptions<MemoryCacheOptions> carCacheOptions)
{
personCache = new MemoryCache(personCacheOptions);
carCache = new MemoryCache(carCacheOptions);
}
public void CreatePersonEntry(Person person)
{
_ = personCache.Set(person, person, TimeSpan.FromHours(1));
}
public void CreateCarEntry(Car car)
{
_ = carCache.Set(car, car, TimeSpan.FromHours(12));
}
}
If you don't have the above requirements, then you could just do what juunas mentioned and create an easy wrapper with a composite key. You still need to ensure GetHashCode is properly implemented for each class you want to store. Here, my composite key is just an integer (I used prime numbers, no specific reason) paired with an object. I didn't use a struct for the key as the MemoryCache uses a Dictionary<object, CacheEntry>, so I don't want to box/unbox the key.
public class CustomCache : ICustomCache // Expose what you need
{
private readonly IMemoryCache cache;
public CustomCache(IMemoryCache cache)
{
this.cache = cache;
}
public void CreatePersonEntry(Person person)
{
_ = cache.Set(CustomKey.Person(person), person, TimeSpan.FromHours(1));
}
public void CreateCarEntry(Car car)
{
_ = cache.Set(CustomKey.Car(car), car, TimeSpan.FromHours(12));
}
private record CompositeKey(int Key, object Value)
{
public static CustomKey Person(Person value) => new(PERSON_KEY, value);
public static CustomKey Car(Car value) => new(CAR_KEY, value);
private const int PERSON_KEY = 1123322689;
private const int CAR_KEY = 262376431;
}
}
Let me know if you see anything wrong, or if there is a better solution.

Related

How to make a Dictionary accessible from all controllers in a .Net 5 API?

I have a Dictionary that will be populated with data from the database at startup, with a method that takes the key as a parameter, and returns the value. How to make the dictionary publicly accessible to all controllers? After searching, I learned that I would need to use Dependency Injection, but I'm failing at implementing it. Any resource that can get me on track is highly appreciated.
There are many ways to implement your question with/without DI. One of which is to write a static class that will be filled upon app startup.
No dependency injection:
Declare a static class that contains your dictionary. By being static there would only be 1 instance on app start.
public static class StaticDictionary {
public Dictionary<string,int> MyDictionary {get;set;}
}
In your Startup.cs - Configure method, append your db context in the parameters.
public void Configure(..., YourDbContext dbContext)
In the Configure method again, append your code that fills the dictionary.
public void Configure(..., YourDbContext dbContext){
...
// no need to modify the code above this, just append the fill dictionary code
foreach(var item in dbContext.TableName.ToList()){
StaticDictionary.MyDictionary.Add(...);
}
}
In your controllers, you could access StaticDictionary without DI.
public IActionResult Index{
var something = StaticDictionary.MyDictionary["Something"];
return View();
}

AutoFixture with AutoNSubstituteCustomization: Set object count on ReadOnly IEnumerable<t> property

My test requires that I have different counts of objects in an IEnumerable property of the main entity collection. I have been searching for documentation about this but can't find anything. Here is a sample of what I mean (note that the base entity is created using AutoNSubstituteCustomization)
IFixture fixture = new Fixture().Customize(new AutoNSubstituteCustomization() { ConfigureMembers = true });
var t = fixture.CreateMany<ITransaction>(5)
var service1 = Substitute.For<ITransactionsSvc>();
service1.GetTransactions().ReturnsForAnyArgs(t);
var service2 = Substitute.For<IRequestsSvc>();
service2.GetRequest(default).ReturnsForAnyArgs(
new Result(){
TransactionId = t.First().Files.First().RequestId
}
);
Where ITransaction would look like
public interface ITransaction
{
long RequestId { get; }
IEnumerable<FileDef> Files { get; }
IEnumerable<Comment> Comments { get; }
}
I know I could set fixture.RepeatCount to specify the global count but how can I have a different value for Files and Comments?
I already tried using t.With(x => x.Files, () => fixture.CreateMany<FileDef>(rnd.Next(1,5)) but it throws saying this is a readonly property.
I also tried using NSubstitute .Returns on the t.Files property but for some reason, the type of RequestId got changed from Int64 to Task`1 when trying to read the value for service2 ReturnForAnyArgs response.
I know I had to remove some of the complexity from the real case so that is stays concise so I hope I didn't remove too much and kept it understandable. If you need any precisions, feel welcome to ask.
Sub-question: is there any complete documentation on AutoFixture? On AutoFixture website I was only able to find very introductory documentation.
It seems that the issue you're having is not related to AutoFixture but rather with NSubstitute.
Since ITransaction is an interface AutoFixture will delegate the task of creating and instance to the mocking library. In your case that's NSubstitute.
Since your interface only declares getters but no setters, NSubstitute will generate a dynamic proxy, for your interface, that as will as well not have any public setters. This is why AutoFixture is unable to set the values of your properties.
So if you want to continue using the mock, you'll have to either specify a public setter in your interface or tell AutoFixture how to set the values using the NSubstitute API. Unfortunately you'll be able to implement the second option only by implementing an ISpecimenBuilder factory for your interface and then play with reflection.
Another way, which is what I recommend, is to relay the setup of your interface to a fake implementation, which you'll create by hand and which will have the public setters. Then you'll instruct AutoFixture to relay all requests to the interface to your fake class.
[Fact]
public void MyTest()
{
var fixture = new Fixture();
fixture.Customize<FakeTransaction>(c => c
.With(x => x.Files, fixture.CreateMany<FileDef>(2).ToList())
.With(x => x.Comments, fixture.CreateMany<Comment>(5).ToList()));
fixture.Customizations.Add(new TypeRelay(typeof(ITransaction), typeof(FakeTransaction)));
ITransaction mock2 = fixture.Create<ITransaction>();
Assert.Equal(2, mock2.Files.Count());
Assert.Equal(5, mock2.Comments.Count());
}
public class FakeTransaction : ITransaction
{
public long RequestId { get; set; }
public IEnumerable<FileDef> Files { get; set; }
public IEnumerable<Comment> Comments { get; set; }
}
Protip: In order to not repeat the relay everywhere, you could create a customization that will add the relay to the fixture, and then combine it with your current NSubstitute customization using CompositeCustomization. Read more here.
About your second question. Unfortunately that is the only "official" documentation. The current effort is going to releasing the next version.
For more info you can refer to the maintainer blogs and this community documentation site. Also there is a cool Pluralsight course available here.
In fact, as #AndreiIvascu mentionned, the problem AND the cleanest solution I found were linked to NSubstitute. Since NSubstitute is creating the instances, theses instances can be configured using standard NSubstitute calls.
The solution is simply to use Returns and ReturnsForAnyArgs as I mentionned but it is essential that this newly created substitute is not used directly in the definition of a second substitute as it was the case when accessing the RequestId.
Note the line var requestId = t.First().Files.First().RequestId; that is now outside of the new Result() definition.
public void MyTest()
{
IFixture fixture = new Fixture().Customize(new AutoNSubstituteCustomization() { ConfigureMembers = true });
var t = fixture.Create<ITransaction>();
t.Files.Returns(fixture.CreateMany<FileDef>(2).ToList());
t.Comments.Returns(fixture.CreateMany<Comment>(5).ToList());
var service1 = Substitute.For<ITransactionsSvc>();
service1.GetTransactions().ReturnsForAnyArgs(t);
var requestId = t.First().Files.First().RequestId;
var service2 = Substitute.For<IRequestsSvc>();
service2.GetRequest(default).ReturnsForAnyArgs(
new Result(){
TransactionId = requestId
}
);
}

Looking for a Ninject scope that behaves like InRequestScope

On my service layer I have injected an UnitOfWork and 2 repositories in the constructor. The Unit of Work and repository have an instance of a DbContext I want to share between the two of them. How can I do that with Ninject ? Which scope should be considered ?
I am not in a web application so I can't use InRequestScope.
I try to do something similar... and I am using DI however, I need my UoW to be Disposed and created like this.
using (IUnitOfWork uow = new UnitOfWorkFactory.Create())
{
_testARepository.Insert(a);
_testBRepository.Insert(b);
uow.SaveChanges();
}
EDIT: I just want to be sure i understand… after look at https://github.com/ninject/ninject.extensions.namedscope/wiki/InNamedScope i though about my current console application architecture which actually use Ninject.
Lets say :
Class A is a Service layer class
Class B is an unit of work which take into parameter an interface (IContextFactory)
Class C is a repository which take into parameter an interface (IContextFactory)
The idea here is to be able to do context operations on 2 or more repository and using the unit of work to apply the changes.
Class D is a context factory (Entity Framework) which provide an instance (keep in a container) of the context which is shared between Class B et C (.. and would be for other repositories aswell).
The context factory keep the instance in his container so i don’t want to reuse this instance all the name since the context need to be disposed at the end of the service operaiton.. it is the main purpose of the InNamedScope actually ?
The solution would be but i am not sure at all i am doing it right, the services instance gonna be transcient which mean they actually never disposed ? :
Bind<IScsContextFactory>()
.To<ScsContextFactory>()
.InNamedScope("ServiceScope")
.WithConstructorArgument(
"connectionString",
ConfigurationUtility.GetConnectionString());
Bind<IUnitOfWork>().To<ScsUnitOfWork>();
Bind<IAccountRepository>().To<AccountRepository>();
Bind<IBlockedIpRepository>().To<BlockedIpRepository>();
Bind<IAccountService>().To<AccountService>().DefinesNamedScope("ServiceScope");
Bind<IBlockedIpService>().To<BlockedIpService>().DefinesNamedScope("ServiceScope");
UPDATE: This approach works against NuGet current, but relies in an anomaly in the InCallscope implementation which has been fixed in the current Unstable NuGet packages. I'll be tweaking this answer in a few days to reflect the best approach after some mulling over. NB the high level way of structuring stuff will stay pretty much identical, just the exact details of the Bind<DbContext>() scoping will work. (Hint: CreateNamedScope in unstable would work or one could set up the Command Handler as DefinesNamedScope. Reason I dont just do that is that I want to have something that composes/plays well with InRequestScope)
I highly recommend reading the Ninject.Extensions.NamedScope integration tests (seriously, find them and read and re-read them)
The DbContext is a Unit Of Work so no further wrapping is necessary.
As you want to be able to have multiple 'requests' in flight and want to have a single Unit of Work shared between them, you need to:
Bind<DbContext>()
.ToMethod( ctx =>
new DbContext(
connectionStringName: ConfigurationUtility.GetConnectionString() ))
.InCallScope();
The InCallScope() means that:
for a given object graph composed for a single kernel.Get() Call (hence In Call Scope), everyone that requires an DbContext will get the same instance.
the IDisposable.Dispose() will be called when a Kernel.Release() happens for the root object (or a Kernel.Components.Get<ICache>().Clear() happens for the root if it is not .InCallScope())
There should be no reason to use InNamedScope() and DefinesNamedScope(); You don't have long-lived objects you're trying to exclude from the default pooling / parenting / grouping.
If you do the above, you should be able to:
var command = kernel.Get<ICommand>();
try {
command.Execute();
} finally {
kernel.Components.Get<ICache>().Clear( command ); // Dispose of DbContext happens here
}
The Command implementation looks like:
class Command : ICommand {
readonly IAccountRepository _ar;
readonly IBlockedIpRepository _br;
readonly DbContext _ctx;
public Command(IAccountRepository ar, IBlockedIpRepository br, DbContext ctx){
_ar = ar;
_br = br;
_ctx = ctx;
}
void ICommand.Execute(){
_ar.Insert(a);
_br.Insert(b);
_ctx.saveChanges();
}
}
Note that in general, I avoid having an implicit Unit of Work in this way, and instead surface it's creation and Disposal. This makes a Command look like this:
class Command : ICommand {
readonly IAccountService _as;
readonly IBlockedIpService _bs;
readonly Func<DbContext> _createContext;
public Command(IAccountService #as, IBlockedIpServices bs, Func<DbContext> createContext){
_as = #as;
_bs = bs;
_createContext = createContext;
}
void ICommand.Execute(){
using(var ctx = _createContext()) {
_ar.InsertA(ctx);
_br.InsertB(ctx);
ctx.saveChanges();
}
}
This involves no usage of .InCallScope() on the Bind<DbContext>() (but does require the presence of Ninject.Extensions.Factory's FactoryModule to synthesize the Func<DbContext> from a straightforward Bind<DbContext>().
As discussed in the other answer, InCallScope is not a good approach to solving this problem.
For now I'm dumping some code that works against the latest NuGet Unstable / Include PreRelease / Instal-Package -Pre editions of Ninject.Web.Common without a clear explanation. I will translate this to an article in the Ninject.Extensions.NamedScope wiki at some stagehave started to write a walkthrough of this technique in the Ninject.Extensions.NamedScope wiki's CreateNamedScope/GetScope article.
Possibly some bits will become Pull Request(s) at some stage too (Hat tip to #Remo Gloor who supplied me the outline code). The associated tests and learning tests are in this gist for now), pending packaging in a proper released format TBD.
The exec summary is you Load the Module below into your Kernel and use .InRequestScope() on everything you want created / Disposed per handler invocation and then feed requests through via IHandlerComposer.ComposeCallDispose.
If you use the following Module:
public class Module : NinjectModule
{
public override void Load()
{
Bind<IHandlerComposer>().To<NinjectRequestScopedHandlerComposer>();
// Wire it up so InRequestScope will work for Handler scopes
Bind<INinjectRequestHandlerScopeFactory>().To<NinjectRequestHandlerScopeFactory>();
NinjectRequestHandlerScopeFactory.NinjectHttpApplicationPlugin.RegisterIn( Kernel );
}
}
Which wires in a Factory[1] and NinjectHttpApplicationPlugin that exposes:
public interface INinjectRequestHandlerScopeFactory
{
NamedScope CreateRequestHandlerScope();
}
Then you can use this Composer to Run a Request InRequestScope():
public interface IHandlerComposer
{
void ComposeCallDispose( Type type, Action<object> callback );
}
Implemented as:
class NinjectRequestScopedHandlerComposer : IHandlerComposer
{
readonly INinjectRequestHandlerScopeFactory _requestHandlerScopeFactory;
public NinjectRequestScopedHandlerComposer( INinjectRequestHandlerScopeFactory requestHandlerScopeFactory )
{
_requestHandlerScopeFactory = requestHandlerScopeFactory;
}
void IHandlerComposer.ComposeCallDispose( Type handlerType, Action<object> callback )
{
using ( var resolutionRoot = _requestHandlerScopeFactory.CreateRequestHandlerScope() )
foreach ( object handler in resolutionRoot.GetAll( handlerType ) )
callback( handler );
}
}
The Ninject Infrastructure stuff:
class NinjectRequestHandlerScopeFactory : INinjectRequestHandlerScopeFactory
{
internal const string ScopeName = "Handler";
readonly IKernel _kernel;
public NinjectRequestHandlerScopeFactory( IKernel kernel )
{
_kernel = kernel;
}
NamedScope INinjectRequestHandlerScopeFactory.CreateRequestHandlerScope()
{
return _kernel.CreateNamedScope( ScopeName );
}
/// <summary>
/// When plugged in as a Ninject Kernel Component via <c>RegisterIn(IKernel)</c>, makes the Named Scope generated during IHandlerFactory.RunAndDispose available for use via the Ninject.Web.Common's <c>.InRequestScope()</c> Binding extension.
/// </summary>
public class NinjectHttpApplicationPlugin : NinjectComponent, INinjectHttpApplicationPlugin
{
readonly IKernel kernel;
public static void RegisterIn( IKernel kernel )
{
kernel.Components.Add<INinjectHttpApplicationPlugin, NinjectHttpApplicationPlugin>();
}
public NinjectHttpApplicationPlugin( IKernel kernel )
{
this.kernel = kernel;
}
object INinjectHttpApplicationPlugin.GetRequestScope( IContext context )
{
// TODO PR for TrgGetScope
try
{
return NamedScopeExtensionMethods.GetScope( context, ScopeName );
}
catch ( UnknownScopeException )
{
return null;
}
}
void INinjectHttpApplicationPlugin.Start()
{
}
void INinjectHttpApplicationPlugin.Stop()
{
}
}
}

How to tackle behavior variation with StructureMap?

I have a set of componentes registered to StructureMap. What should be the best way to resolve a component depending on the actual Tenant?
Small example:
There are two tenants, say, Yellow and Green.
I have an IValidator that has two implementations: YellowValidator and GreenValidator.
Say the application is MVC and that the tentant comes form the URL.
So, I just need the proper IValidator to be injected depending on the tenant.
I've seen many solutions for multi-tenant applications that deals only with multitenancy of data, normaly configuring different databases depending on the tenant. That involves only parameter passing. But this is the case where variation occurs in behavior, not in data. I want the IoC container to Resolve the right instance transparently.
EDIT: more info:
The IValidator interface have a simple method bool Validate(), but the implementation require some injection.
There are other custom validators, but they are used by both tenants.
There is a clear tentant strategy based on the URL. This means that each request can have a different tenant, and that a single application serves both tenants.
There are many ways to skin a cat. It's hard for me to guess the design of your application, so here is an idea. Things that come in mind are to hide validators behind a composite, to allow users of the IValidator interface to know nothing about having many implementations. Such composite can look like this:
public class ValidatorComposite : IValidator
{
private IEnumerable<IValidator> validators;
public ValidatorComposite(
IEnumerable<IValidator> validators)
{
this.validators = validators;
}
public bool Validate(object instance)
{
return this.validators.All(v => v.Validate(instance));
}
}
You can create multiple composites and register them by key where the key is the name of the tenant (but without keyed registrations is probably just as easy). Those composites can be wrapped in yet another composite that will delegate to the proper tenant-specific composite. Such a tenant-selecting composite could look like this:
public class TenantValidatorComposite : IValidator
{
private ITenantContext tenantContext;
private IValidator defaultValidator;
private IDictionary<string, IValidator> tenantValidators;
public ValidatorComposite(
ITenantContext tenantContext,
IValidator defaultValidator,
IDictionary<string, IValidator> tenantValidators)
{
this.tenantContext = tenantContext;
this.defaultValidator = defaultValidator;
this.tenantValidators = tenantValidators;
}
public bool Validate(object instance)
{
string name = this.tenantContext.CurrentTenant.Name;
return this.defaultValidator.Validate(instance) &&
this.tenantValidators[name].Validate(instance);
}
}
The ITenantContext is an abstraction that allows you to get the current tenant within the current context. You probably already have something like that in place, but I imagine an implementation to look something like this:
class UrlBasedTenantContext : ITenantContext
{
public Tenant Current
{
get
{
// Naive implementation.
if (HttpContext.Current.Request.Url.Contains("tenant1"))
{
return Tenant1;
}
return Tenant2;
}
}
}
Create a TenantValidatorComposite would be easy:
var defaultValidator = CompositeValidator(
GetAllDefaultValidators());
var tenantValidators = new Dictionary<string, IValidator>()
{
{ "tenant1", new CompositeValidator(GetValidatorsFor("tenant1")) },
{ "tenant2", new CompositeValidator(GetValidatorsFor("tenant2")) },
};
var tenantValidator = new TenantValidatorComposite(
new UrlBasedTenantContext(),
defaultValidator,
tenantValidators);
I hope this helps.

NHibernate - why is this static method legal in this domain class?

I have read in Chapter 4 of the NHibernate docs that all of a persistent classes public methods, properties and events must be declared as virtual.
However, whilst a runtime error is generated for any Properties that are not marked as virtual, I have found that static methods are allowed and do not generate a runtime error . As they are static they are of course not marked virtual which seems to break the rule in point 4.1.4 of the documentation (see above). I have checked the resulting sql and it also implements lazy loading correctly when I run a test against the method so is it therefore ok to use static methods?
Here's the basic details of the persistant class:
public class CmsPage
{
public virtual int? Id { get; set; }
public virtual string Title { get; set; }
public virtual void Update()
{
using (ISession session = NHibernateHelper.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
session.Update(this);
transaction.Commit();
}
}
}
// Note: static and non-virtual and yet it will not cause a problem for Nhibernate
public static IEnumerable<CmsPage> GetList()
{
IList<CmsPage> pageList;
using (ISession session = NHibernateHelper.OpenSession())
{
string hql = "from CmsPage p";
pageList = session.CreateQuery(hql)
.List<CmsPage>();
}
return pageList;
}
}
So my question is why is it ok to use a static method in the persistent domain class when the documentation seems to say it's not?
Please answer from NHibernate's point of view not an OO design point of view; I don't want to get into an OOD/OOP debate if it can be avoided please.
The documentation says: "NHibernate works best if these classes follow some simple rules, ..." It doesn't say it won't work (clearly it does work).
So, really, the discussion boils down to an OO issue.
Actually this applies only to properties. Methods are not persisted, so proxies and lazy-loading does not apply. Ideally you should separate data access (the static methods in your case) from the domain object. But you are correct to point this out, maybe the documentation should have been clearer.
In conclusion your class is perfectly fine but it could be even better if you separated the concerns.
NHibernate needs all your properties to be virtual because it carries out its lazy-loading magic by making proxies of your objects that override everything. So when you write this code:
class Foo {
public virtual Foo[] Neighbors { get; set; }
}
NHibernate secretly generates classes like:
class NHProxy03450843275 : Foo {
public virtual Foo[] Neighbors { /* Godawful lazy-loading magic goes here */ }
}
Actually it's worse than that, but this gives you the idea. Anyway, static methods aren't bound to particular instances of a class, so NH doesn't need proxies to deal with them. Thus they can be non-virtual.