ServiceClient Caching Resutls - dataverse

I am using ServiceClient to access data in dataverse from a c# application. The application is a worker service and the service client is injected into the application using dependency injection as a singleton. I am seeing the service client cache results. Is there a work around for this. If I update the record in dataverse my application continues to pull the old data.

It appears since my context was a singleton I needed to detatch any records that I may have already queried.

Related

addScoped service lifetime in an ASP.NET Core multithreaded application

I know that AddSingleton() creates a single instance of the service when it is first requested and reuses that same instance in all the places where that service is needed.
If my ASP.NET Core application is multi-threaded, does that mean all HTTP requests from all users will share the same object instance created by dependency injection (DI)?
If so, that would be not a good way if the application process data to be stored. Are there any best practices?
As mentioned in Microsoft documentation, Service lifetimes, it depends on your specific case.
Presumably, if you have a service, A, and you want to create a new instance on every single request, you can use AddScoped() rather than AddSingleton(). A scoped lifetime service would be created per client request.
If for example, it was some shared data that possibly doesn't change between requests such as some values that are computed at application startup and reused throughout the lifetime of the application, then that is a usable scenario.

How to cache Entity Framework Core model?

I have an Azure fabric cluster with .NET core 2.2 micro services inside of it. The mentioned services use EF core for communicating with Azure SQL databases. Also, the fabric cluster is behind a load balancer.
The database context has a scoped lifetime and is injected into the controllers using dependency injection.
Everything works well when the services are queried consistently by the same client, since the load balancer guarantees that for at least 4 minutes the same user will be sent to the same service instance. However, when the load balancer decides to send the user to a different instance, the database context is created again (since the lifetime is scoped, it means that a context is created per new web request). Unfortunately, the model building process takes quite long and due to that reason the first query is always way slower than the subsequent ones (on the same web request).
The questions would be, is it possible to somehow cache the EF Core model, so that it wouldn't have to be rebuilt every time the situation described above occurs ?
I mean, a similar procedure to EF - where an .edmx file is created once and loaded on context creation.
As of 3/3/2020 https://github.com/dotnet/efcore/issues/1906 this is still not possible.
If you need model caching for performance reasons you will need to use EF 6. The good news is that EF 6.3 and the the SQL Server provider for EF 6 were ported over to run on .net core 3.0. However other providers may or may not port their code over so support may be spotty.
https://devblogs.microsoft.com/dotnet/announcing-ef-core-3-0-and-ef-6-3-general-availability/#what-s-new-in-ef-6-3

Application level variables in web api c#

I am in a situation where requirement is to keep an application level object in web api which can be accessed by all requests. I know one can use HttpContext.Current but that is not required since HttpContext is only for the liftime of request. I need a solution where i can keep an object that all requests can access and update as required.
Use a static class to hold your application level objects. static classes and static data members are created once for the application lifetime and all ASP.NET requests can access them.
I learnt it the hard way. Some time back, I mistakenly created a static field to hold customer-specific database connection string, in a ASP.NET Web API project and it became a mess. On each customer's login it was being set (overridden) in the code and the requests from the previously logged customers were using this newly set static SQL connection string for their queries. It was an embarrassing situation when customer's inadvertently saw each other's data.
You could use SessionState (per session).
I.e.
Session["YourDataKey"] = ApplicationLevelObject;
And then check the session state variable on each request that requires it.
However if you require the object for longer, I.e. every single user session, then I would suggest persisting your object to a database. You could use an ORM such as Entity Framework.
Cheers

What's the lifetime of an object using SignalR with Unity Dependency Resolver?

Let me start with a little setup info... I am using the repository pattern and dependency injection via Unity. The repository is implemented via Linq-To-Sql. I inject my repositories into class constructors in my web project. The repositories have a PerWebRequest lifetime.
I have implemented a few SignalR hubs and have setup a Unity dependency resolver for SignalR. I'm injecting the same repositories into the hubs using the same Unity config file, which specifies these repositories are PerWebRequest also.
Now the punchline... I ran into a problem where the web project would update an Linq-To-Sql entity and the SignalR hub would read that entity and not get the updates. I have "solved" this problem by clearing the Linq-To-Sql cache before reading the entity in the SignalR hub; DataContact.Refresh() didn't update the entire object graph.
My DataContext for these repositories used in hubs are also PerWebRequest but it seams that the SignalR hubs are using a separate DataContext that does not get destroyed after the web request completes. It appears they are acting as singleton instances instead.
Do SignalR apps run in their own process and therefore my DataContext access from the hubs is a separate DataContext in that separate process?
How could the DataContext in the SignalR hub be instantiated with a PerWebRequest lifetime if it a separate process, apart from the web request lifecycle? Also, how does it seemingly act like a Singleton?
It's a while I don't use stuff like Linq2Sql or concepts like PerWebRequest, so I'm not 100% sure, but if I'm correct in saying that PerWebRequest is definitely tied to the lifetime of underlying HTTP requests, then those will hardly work with SignalR because its behavior can change a lot according to the chosen transport strategy. With WebSockets you might have several hub instantiations/method calls over the same connection, while with Long Polling you would probably have one (or zero) per HTTP request. Check here and here.
Given that the code you write with SignalR should be the same regardless of the transport, I think for hubs you'd always have to handle repositories in a specific way, maybe with an ad-hoc factory always clearing the cache each time a repository has to be supplied to a SignalR hub (you could try to be smart and check the transport strategy used, but those could be muddy waters).

Signalr webfarm with Backplane out of sync

We have a SignalR application that we built and tested for use on a single web server. The requirements have changed and we need to deploy the application to a webfarm. SignalR supports several backplanes, since the application already uses Sql Server that is what we have implemented. With the introduction of a second web node we ran into an issue with keeping the data that is cached within the Hub synced between the nodes.
Each hub has an internal cache in the form of a DataSet.
private static DataSet _cache; The cache gets populated when a client first requests data, and from there any interaction updates the local cache and the sql server, then notifies all connected clients of the changes.
The backplane handles the broadcast messages between the clients but the other node does not receive a message.
Our first thought was that there might be a method that we could wire up that would triggered from the backplane sending a message to a nodes clients, but we have not seen such a thing mentioned in documentation.
Our second thought was to create a .net client within the hub.
private async void ConnectHubProxy()
{
IHubProxy EventViewerHubProxy = _hubConnection.CreateHubProxy("EventViewerHub");
EventViewerHubProxy.On<string>("BroadcastAcknowledgedEvents", EventIDs => UpdateCacheIsAcknowledged(EventIDs));
EventViewerHubProxy.On<string>("BroadcastDeletedEvents", EventIDs => UpdateCacheIsDeleted(EventIDs));
ServicePointManager.DefaultConnectionLimit = 10;
await _hubConnection.Start();
}
Our questions:
How do we keep the cache in sync?
Is the first thought possible and we missed it in the documentation?
Are there any issues concerns with having a hub connect to itself?
The recommended way to have "state" in a scaleout scenario is to have a source of persistence. So in your case, if you're looking to have a "global-like" cache one way you can implement that is via a database.
By creating a database all your nodes can write/read from the same source and therefore have a global cache.
The reason why having an in-memory cache is not a good idea is because in a web farm, if nodes go down, they then lose all their in-memory cache. By having persistence, it doesn't matter if a nodes been up for days or has just recovered from a "shutdown" based failure, the persistence layer is always there.

Resources