Azure Redis StackExchange.Redis ConnectionMultiplexer in ASP.net MVC - c#

I have read that in order to connect to Azure Redis cache is best to follow this practice:
private static ConnectionMultiplexer Connection { get { return LazyConnection.Value; } }
private static readonly Lazy<ConnectionMultiplexer> LazyConnection =
new Lazy<ConnectionMultiplexer>(
() =>
{
return
ConnectionMultiplexer.Connect(connStinrg);
});
And according to Azure Redis docs:
The connection to the Azure Redis Cache is managed by the ConnectionMultiplexer class. This class is designed to be shared and reused throughout your client application, and does not need to be created on a per operation basis.
So what is best practice for sharing ConnectionMultiplexer across my ASP.net MVC app ?
Should it be called in Global.asax, or should I initialize it once per Controller, or smth. else ?
Also I have service which is tasked to communicate with the app, so if I want to communicate with Redis inside the Service should I send instance of ConnectionMultiplexer to service from Controllers, or should I initialize it in all my services, or ?
As you can see I'm a bit lost here, so please help !

The docs are right in that you should have only one instance of ConnectionMultiplexer and reuse it. Don't create more than one, it is recommended that it will be shared and reused.
Now for the creation part, it shouldn't be in Controller or in Global.asax. Normally you should have your own RedisCacheClient class (maybe implementing some ICache interface) that uses a ConnectionMultiplexer private static instance inside and that's where your creation code should be - exactly as you wrote it in your question. The Lazy part will defer the creation of the ConnectionMultiplexer until the first time it is used.

Dears;
You can reuse StackExchange.Redis ConnectionMultiplexer by using the following code. It can be used in any layer of your code.
public class RedisSharedConnection
{
private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
ConnectionMultiplexer connectionMultiplexer = ConnectionMultiplexer.Connect(ConfigurationManager.ConnectionStrings["RedisConnectionString"].ConnectionString);
connectionMultiplexer.PreserveAsyncOrder = false;
return connectionMultiplexer;
});
public static ConnectionMultiplexer Connection
{
get
{
return lazyConnection.Value;
}
}
}

Related

How to prevent that Dynamics 365 authenticates every time a CrmServiceClient connection is made

We are in the process of migrating from Dynamics on-prem to Dynamics 365 online. So we had to change also a webapp that is connecting to Dynamics.
The webapp is still working but the performance is poor. We started to do some traces to see why. In this trace we saw that the app is doing for a single request different calls to Dynamics online. Reason for this is that we are indeed retrieving different sets of data. But we are surprised to see that authentication is done also multiple times. This authentication is slowing down the response from dynamics. We were expecting that authentication was done only with the first request.
The code I'm using to make the connection is in an abstract class that is instantiated by different other classes. This classes are using the following property returning a CrmServiceClient from the namespace Microsoft.Xrm.Tooling.Connector:
protected CrmServiceClient CustomCrmServiceProxy
{
get
{
CrmServiceClient client = new CrmServiceClient(CrmConnection.Connectionstring);
client.CallerId = GetCallerId();
return client;
}
}
The connectionstring is AuthType=ClientSecret;url={0};ClientId={1};ClientSecret={2}; with the values replaced.
In the classes using the abstract class we are calling the property like
var data = this.CustomCrmServiceProxy.RetrieveMultiple("fetch xml");
Important is that we are passing the callerid to the CrmServiceClient and this one can be different when the visitor switch to a page in another language.
Is there a way to prevent the multiple authentication?
Is implementing a singleton pattern an option? But what with the different callerids in that case? And is there maybe a good example for CrmServiceClient?
The CrmServiceClient offers a number of constructors giving the opportunity to reuse a connection instance.
E.g. the following constructor overload has parameter useUniqueInstance. Pass a false value to it when a cached instance should be used.
public CrmServiceClient(string userId, SecureString password, string domain, string homeRealm, string hostName, string port, string orgName, bool useUniqueInstance = false, bool useSsl = false, OrganizationDetail orgDetail = null)
In most cases however a web app will be consumed by multiple clients, often concurrently, and a singleton connection object would not scale well in those scenarios. In these cases you can introduce a connection pool.
A connection pool class would be responsible for maintaining a collection of CrmServiceClient instances. A factory pattern could be used to claim instances from the pool object. When disposed, the factory instance returns all claimed instances to the pool.
Your factory class could implement the existing IOrganizationServiceFactory. This interface is designed with impersonation requirements in mind.
Note: do not make classes that currently use CrmServiceClient connections responsible for creating these instances. Instead inject IOrganizationServiceFactory or IOrganizationService objects into the constructors of these classes.
Can you try something like this?
This would create a single instance of the connection (with the callerID) and then just continually refer to that instance.
CrmServiceClient _client = null;
protected CrmServiceClient CustomCrmServiceProxy
{
get
{
if (_client == null)
{
_client = new CrmServiceClient(CrmConnection.Connectionstring);
_client.CallerId = GetCallerId();
}
return _client;
}
I have seen situations where a program executes a get accessor more times than I think it should.
Rather than having it as a property, I'd say try making it a method.
protected CrmServiceClient GetService()
{
var client = new CrmServiceClient(CrmConnection.Connectionstring);
client.CallerId = GetCallerId();
return client;
}
Then, one option for lazy instantiation would be:
private CrmServiceClient _svc;
private CrmServiceClient svc => _svc ?? (_svc = GetService());

How to Per-Request caching in ASP.net core

My old code looks like this:
public static class DbHelper {
// One conection per request
public static Database CurrentDb() {
if (HttpContext.Current.Items["CurrentDb"] == null) {
var retval = new DatabaseWithMVCMiniProfiler("MainConnectionString");
HttpContext.Current.Items["CurrentDb"] = retval;
return retval;
}
return (Database)HttpContext.Current.Items["CurrentDb"];
}
}
Since we don't have HttpContext anymore easily accesible in core, how can I achieve the same thing?
I need to access CurrentDb() easily from everywhere
Would like to use something like MemoryCache, but with Request lifetime. DI it's not an option for this project
There are at least 3 options to store an object per-request in ASP.NET Core:
1. Dependency Injection
You could totally re-design that old code: use the built-in DI and register a Database instance as scoped (per web-request) with the following factory method:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<Database>((provider) =>
{
return new DatabaseWithMVCMiniProfiler("MainConnectionString");
});
}
Introduction to Dependency Injection in ASP.NET Core
.NET Core Dependency Injection Lifetimes Explained
2. HttpContext.Items
This collection is available from the start of an HttpRequest and is discarded at the end of each request.
Working with HttpContext.Items
3. AsyncLocal<T>
Store a value per a current async context (a kind of [ThreadStatic] with async support). This is how HttpContext is actually stored: HttpContextAccessor.
What's the effect of AsyncLocal<T> in non async/await code?
ThreadStatic in asynchronous ASP.NET Web API
Will not the database or connection string would be same across the
requests?
If so then you could do it by a static variable and middleware.
The middleware would check and set the info on each request start and static variable would store the value then your method could read it from the static variable.
Other simpler approach would be to inject/pass the IHttpContextAccessor as parameter. With this you could do with minimal changes but you have the pass the IHttpContextAccessor service from each calling method.

NHibernate Performance and Scalability

I have a web forms site that use NHibernate to connect to a MSSQL database.
I use the following class to create the SessionFactory and get the current session to use:
internal static class SessionManager
{
static readonly Configuration Configuration = new Configuration().Configure();
internal readonly static ISessionFactory SessionFactory = Configuration.BuildSessionFactory();
internal static ISession CurrentSession { get { if (!CurrentSessionContext.HasBind(SessionFactory))CurrentSessionContext.Bind(SessionFactory.OpenSession()); return SessionFactory.GetCurrentSession(); } }
}
And that is an example of how I use the previous one:
public abstract class Repository<TEntity>
{
protected internal ISession Session { get { return SessionManager.CurrentSession; } }
public IQueryable<TEntity> AllItems { get { return Session.Query<TEntity>(); } }
}
Everything works fine, although I believe I'm doing something really bad in terms of performance and scalability, but I can't see what.
Can anyone point me out what is and/or suggest a better way to handle this?
Thanks in advance!
I think the main issue in your code is that, when you put the Session object as a static field in a static class, you will have only one session for the whole process, what can bring you problems, like "a different object with the same identifier value was already associated with the session", for example.
What you could do is create another static method to allow you to close the session, but you would have to control when to close it (in a web environment, it could be in the end of every Request), or you could use some dependency injection framework like NInject or Castle Windsor to control the lifetime of the Session object.
Take a look at this:
(Yet another) nHibernate sessionmanager for ASP.NET (MVC)
Effective NHibernate Session management for web apps

NHibernate: Is making session singleton a bad practice?

In my application I have the session as a singleton object in a SessionManager class. Whenever, I need to use it a some part of the application, I do:
using (var session = SessionManager.OpenSession())
{
}
Is this possibly a bad practice ? If so, any ideas about how I can improve ?
EDIT: Here is the implementation of session manager
public static class SessionManager
{
private static readonly ISessionFactory sessionFactory;
static SessionManager()
{
sessionFactory = Fluently.Configure().....
}
public static ISessionFactory SessionFactory
{
get { return sessionFactory; }
}
public static ISession OpenSession()
{
return sessionFactory.OpenSession();
}
}
Please note that the ISession is not thread-safe! Therefore, you should have just one ISessionFactory, but one ISession per thread.
No, it should be singleton so that it can be shared among different threads withing the application. As these objects are heavy weight because they contains the connection information, hibernate configuration information and mapping files,location path. So creating number of instances will make our application heavy weight. But the session objects are not thread safe.
Only applications that require multiple factories with different configurations have an obvious reason to create and close multiple SessionManager instances.
Single threading it will improve the performance of your application.

NHibernate: Configure() in every page request?

I have been reading many books on NHibernate and have noticed how the Configure() is implemented. In the books that method is called every time the application is run in a console application. Most of the ASP.NET examples online call Configure() on every page request. I think this will have alot of overhead since NHibernate must be configured on every request. Does it matter if NHibernate is configured on every page request? If not, how would someone save the configuration - application wide in asp.net mvc?
NHibernate is designed to be configured once per application start. In the case of a console program, that's every time you run the program. In the case of an ASP.NET application, that's every time the application starts, firing the Application.Start event.
The SessionFactory NHibernate creates from Configure() is safe to be cached for the lifetime of the application and is thread-safe to create sessions repeatedly. There is no need to configure on every request.
In the most basic way, you can use a lazy-initialized static property to safely give you a singleton for your application to use:
public static class NHibernateSessions
{
private static readonly Lazy<SessionFactory> lazyFactory;
static NHibernateSessions
{
lazyFactory = new Lazy<SessionFactory >(
() => NHibernateSessions.CreateSessionFactory());
}
public static SessionFactory Factory
{
get
{
return NHibernateSessions.lazyFactory.Value;
}
}
public static void Initialize()
{
if(!NHibernateSessions.lazyFactory.IsValueCreated)
{
// Access the value to force initialization.
var factory = lazyFactory.Value;
}
}
private static SessionFactory CreateSessionFactory()
{
// Add code here to configure and create factory.
}
}
This code uses the Lazy<T> type, to ensure the initialization is thread-safe. You can then call NHibernateSessions.Factory to get the singleton factory with which to re-use throughout your application.
By default the factory is initialized on the first get of the Factory property. This means that for an ASP.NET application, the first request to attempt to use NHibernate will be a slow one. If this is a problem, you can force initialization when the application starts by calling the Initialize() method in an Application.Start event-handler.

Categories

Resources