在 .NET Core 2 中存储和检索 IDistributedCache (Redis) 中的值
Storing and retrieving values from IDistributedCache (Redis) in .NET Core 2
我有一个 ASP.NET Core2 应用程序。我同时使用内置和 Autofac IoC 容器。我正在 Startup.cs 文件中设置所有组件注册。在执行此操作时,我还设置了我的 DBContext,它继承自自定义 DataContext,后者又继承自 DbContext 并实现自定义 IDataContextAsync。此 DbContext 需要连接字符串作为构造函数参数。
我的问题是连接字符串存储在 IDistributedCache 的 Redis 缓存中。缓存设置在 startup.cs 文件中。 Startup.cs 中的同一 ConfigureServices 方法也需要连接字符串。所以,我现在似乎无法访问这个缓存。
当我使用 HttpContext Session 存储连接字符串时,一切正常。现在应用程序正在部署到 Web 场,我不能在 proc 会话中使用。我们使用 Redis 进行状态管理。这是我遇到问题的地方。
这是 startup.cs 文件中的 ConfigureServices 方法(为简洁起见删除了不必要的代码)。
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddJsonOptions(op => op.SerializerSettings.ContractResolver = new DefaultContractResolver());
services.AddSession(opt =>
{
opt.IdleTimeout = TimeSpan.FromMinutes(20);
opt.Cookie.Name = "apexportal.RulesSession";
opt.Cookie.HttpOnly = true;
});
services.AddDistributedRedisCache(o =>
{
var host = Configuration.GetValue<string>($"{AppConstants.REDIS}:{AppConstants.REDISHOST}");
var port = Configuration.GetValue<string>($"{AppConstants.REDIS}:{AppConstants.REDISPORT}");
o.Configuration = $"{host}";
o.InstanceName = Configuration.GetValue<string>($"{AppConstants.REDIS}:{AppConstants.REDISNAME}");
});
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
//services.AddTransient<IConnectionStringProvider, ConnectionStringProvider>();
services.AddTransient<IDataContextAsync>(s => new PortalEFContext(GetPortalConnectionString()));
services.AddAuthentication(IISDefaults.AuthenticationScheme);
ContainerBuilder builder = new ContainerBuilder();
builder.Populate( services );
var container = builder.Build();
return container.Resolve<IServiceProvider>();
}
这是我的 GetPortalConnectionString() 方法,它也在 startup.cs 文件中。我想用注入的 RedisCache.Get().
替换行 accessor.HttpContext.Session.Get()
private string GetPortalConnectionString()
{
IHttpContextAccessor accessor = new HttpContextAccessor();
//this is where I need to access the RedisCache and access the stored properties
// instead of using HttpContext.Session. But I don't know how to inject the IDistributedCache
// to this spot.
var connString = accessor.HttpContext.Session.Get<string>(AppConstants.SPCONNSTRING);
return connString ?? Configuration.GetConnectionString("PortalEFContext");
}
稍后,当用户选择要在应用程序中使用的数据库时,我会像这样在 Redis 缓存中存储到该数据库的连接字符串。
这是我的 BaseController class 做的。
public abstract class BaseController : Controller
{
//private readonly IRulesEngineService reService;
protected readonly IHttpContextAccessor httpCtxAccessor;
protected readonly IConfiguration config;
private readonly IAuthService authService;
protected readonly IDistributedCache redisCache;
public BaseController(IHttpContextAccessor _httpContext, IConfiguration _config, IAuthService _authService, IDistributedCache _redisCache)
{
//reService = _reService;
httpCtxAccessor = _httpContext;
config = _config;
authService = _authService;
redisCache = _redisCache;
//SetupCurrentWindowsUserAsync();
}
protected async Task<string> SetCurrentDBConnString( int dbId )
{
var currDbId = await GetCurrentDBId();
if ( currDbId == 0 || currDbId != dbId )
{
var envConnStr = config.GetConnectionString( AppConstants.ENVCONNSTRING );
var connStr = await AppHelper.SetCurrentDBConnectionString( dbId, envConnStr );
//httpCtxAccessor.HttpContext.Session.Set<string>( AppConstants.SPCONNSTRING, connStr );
//httpCtxAccessor.HttpContext.Session.Set<int>( AppConstants.CURRDBID, dbId );
await redisCache.SetAsync<string>( AppConstants.SPCONNSTRING, connStr );
await redisCache.SetAsync<int>( AppConstants.CURRDBID, dbId );
await SetupCurrentWindowsUserAsync();
return connStr;
}
return null;
}
}
谁能告诉我如何访问 startup.cs 文件中的 Redis 缓存?谢谢
其实很简单。你快到了。
仔细看看你启动时的这一行:
services.AddTransient<IDataContextAsync>(s => new PortalEFContext(GetPortalConnectionString()));
看到 lambda 中的 s
参数了吗?这是 .NET Core 的 DI 容器,名为 IServiceProvider
。这就是您要找的。只需将它传递到您的函数中,然后在那里使用它来解决您想要的任何问题。
所以,代码如下:
public IServiceProvider ConfigureServices(IServiceCollection services)
...
services.AddTransient<IDataContextAsync>(s => new PortalEFContext(GetPortalConnectionString(s))); // <-- pass the container to the function
...
}
private string GetPortalConnectionString(IServiceProvider container)
{
// Here you go:
var cache = container.GetService<IDistributedCache>();
// and now do whatever you want with it.
var connString = cache.Get<string>(AppConstants.SPCONNSTRING);
// BTW, configuration can be resolved from container as well in order to avoid hard dependency on global Configuration object:
var config = container.GetService<IConfiguration>();
return connString ?? config.GetConnectionString("PortalEFContext");
}
我有一个 ASP.NET Core2 应用程序。我同时使用内置和 Autofac IoC 容器。我正在 Startup.cs 文件中设置所有组件注册。在执行此操作时,我还设置了我的 DBContext,它继承自自定义 DataContext,后者又继承自 DbContext 并实现自定义 IDataContextAsync。此 DbContext 需要连接字符串作为构造函数参数。
我的问题是连接字符串存储在 IDistributedCache 的 Redis 缓存中。缓存设置在 startup.cs 文件中。 Startup.cs 中的同一 ConfigureServices 方法也需要连接字符串。所以,我现在似乎无法访问这个缓存。
当我使用 HttpContext Session 存储连接字符串时,一切正常。现在应用程序正在部署到 Web 场,我不能在 proc 会话中使用。我们使用 Redis 进行状态管理。这是我遇到问题的地方。
这是 startup.cs 文件中的 ConfigureServices 方法(为简洁起见删除了不必要的代码)。
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddJsonOptions(op => op.SerializerSettings.ContractResolver = new DefaultContractResolver());
services.AddSession(opt =>
{
opt.IdleTimeout = TimeSpan.FromMinutes(20);
opt.Cookie.Name = "apexportal.RulesSession";
opt.Cookie.HttpOnly = true;
});
services.AddDistributedRedisCache(o =>
{
var host = Configuration.GetValue<string>($"{AppConstants.REDIS}:{AppConstants.REDISHOST}");
var port = Configuration.GetValue<string>($"{AppConstants.REDIS}:{AppConstants.REDISPORT}");
o.Configuration = $"{host}";
o.InstanceName = Configuration.GetValue<string>($"{AppConstants.REDIS}:{AppConstants.REDISNAME}");
});
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
//services.AddTransient<IConnectionStringProvider, ConnectionStringProvider>();
services.AddTransient<IDataContextAsync>(s => new PortalEFContext(GetPortalConnectionString()));
services.AddAuthentication(IISDefaults.AuthenticationScheme);
ContainerBuilder builder = new ContainerBuilder();
builder.Populate( services );
var container = builder.Build();
return container.Resolve<IServiceProvider>();
}
这是我的 GetPortalConnectionString() 方法,它也在 startup.cs 文件中。我想用注入的 RedisCache.Get().
替换行 accessor.HttpContext.Session.Get()private string GetPortalConnectionString()
{
IHttpContextAccessor accessor = new HttpContextAccessor();
//this is where I need to access the RedisCache and access the stored properties
// instead of using HttpContext.Session. But I don't know how to inject the IDistributedCache
// to this spot.
var connString = accessor.HttpContext.Session.Get<string>(AppConstants.SPCONNSTRING);
return connString ?? Configuration.GetConnectionString("PortalEFContext");
}
稍后,当用户选择要在应用程序中使用的数据库时,我会像这样在 Redis 缓存中存储到该数据库的连接字符串。
这是我的 BaseController class 做的。
public abstract class BaseController : Controller
{
//private readonly IRulesEngineService reService;
protected readonly IHttpContextAccessor httpCtxAccessor;
protected readonly IConfiguration config;
private readonly IAuthService authService;
protected readonly IDistributedCache redisCache;
public BaseController(IHttpContextAccessor _httpContext, IConfiguration _config, IAuthService _authService, IDistributedCache _redisCache)
{
//reService = _reService;
httpCtxAccessor = _httpContext;
config = _config;
authService = _authService;
redisCache = _redisCache;
//SetupCurrentWindowsUserAsync();
}
protected async Task<string> SetCurrentDBConnString( int dbId )
{
var currDbId = await GetCurrentDBId();
if ( currDbId == 0 || currDbId != dbId )
{
var envConnStr = config.GetConnectionString( AppConstants.ENVCONNSTRING );
var connStr = await AppHelper.SetCurrentDBConnectionString( dbId, envConnStr );
//httpCtxAccessor.HttpContext.Session.Set<string>( AppConstants.SPCONNSTRING, connStr );
//httpCtxAccessor.HttpContext.Session.Set<int>( AppConstants.CURRDBID, dbId );
await redisCache.SetAsync<string>( AppConstants.SPCONNSTRING, connStr );
await redisCache.SetAsync<int>( AppConstants.CURRDBID, dbId );
await SetupCurrentWindowsUserAsync();
return connStr;
}
return null;
}
}
谁能告诉我如何访问 startup.cs 文件中的 Redis 缓存?谢谢
其实很简单。你快到了。
仔细看看你启动时的这一行:
services.AddTransient<IDataContextAsync>(s => new PortalEFContext(GetPortalConnectionString()));
看到 lambda 中的 s
参数了吗?这是 .NET Core 的 DI 容器,名为 IServiceProvider
。这就是您要找的。只需将它传递到您的函数中,然后在那里使用它来解决您想要的任何问题。
所以,代码如下:
public IServiceProvider ConfigureServices(IServiceCollection services)
...
services.AddTransient<IDataContextAsync>(s => new PortalEFContext(GetPortalConnectionString(s))); // <-- pass the container to the function
...
}
private string GetPortalConnectionString(IServiceProvider container)
{
// Here you go:
var cache = container.GetService<IDistributedCache>();
// and now do whatever you want with it.
var connString = cache.Get<string>(AppConstants.SPCONNSTRING);
// BTW, configuration can be resolved from container as well in order to avoid hard dependency on global Configuration object:
var config = container.GetService<IConfiguration>();
return connString ?? config.GetConnectionString("PortalEFContext");
}