.NET开发中全局数据存储的常见方式
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">一、静态类与静态成员</a></li><li><a href="#_label1">二、应用程序配置系统</a></li><li><a href="#_label2">三、依赖注入容器</a></li><li><a href="#_label3">四、内存缓存 (IMemoryCache)</a></li><li><a href="#_label4">五、分布式缓存 (IDistributedCache)</a></li><li><a href="#_label5">六、HttpContext.Items (ASP.NET Core)</a></li><li><a href="#_label6">七、环境变量</a></li><li><a href="#_label7">八、数据库存储</a></li><li><a href="#_label8">九、选择指南</a></li><li><a href="#_label9">十、最佳实践建议</a></li><li><a href="#_label10">十一、高级模式示例</a></li><ul class="second_class_ul"><li><a href="#_lab2_10_0">混合缓存策略</a></li><li><a href="#_lab2_10_1">配置热重载</a></li></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>一、静态类与静态成员</h2><p>实现方式</p>
<div class="jb51code"><pre class="brush:csharp;">public static class GlobalData
{
public static string ApplicationName { get; set; } = "MyApp";
public static int MaxConnections { get; } = 100;
private static readonly ConcurrentDictionary<string, object> _cache
= new ConcurrentDictionary<string, object>();
public static void SetCache(string key, object value)
{
_cache = value;
}
public static T GetCache<T>(string key)
{
return _cache.TryGetValue(key, out var value) ? (T)value : default;
}
}</pre></div>
<p><strong>特点</strong></p>
<ul><li>生命周期:应用程序域生命周期</li><li>线程安全:需要手动实现(如使用 ConcurrentDictionary)</li><li>适用场景:小型应用、工具类、全局配置</li></ul>
<p><strong>优缺点</strong></p>
<ul><li>简单易用</li><li>访问速度快</li><li>缺乏持久化</li><li>测试困难(静态依赖)</li></ul>
<p class="maodian"><a name="_label1"></a></p><h2>二、应用程序配置系统</h2>
<p>1. appsettings.json (ASP.NET Core)</p>
<div class="jb51code"><pre class="brush:json;">{
"AppConfig": {
"Theme": "Dark",
"Timeout": 30
}
}
</pre></div>
<p>使用方式</p>
<div class="jb51code"><pre class="brush:csharp;">// 在Startup中配置
services.Configure<AppConfig>(Configuration.GetSection("AppConfig"));
// 注入使用
public class MyService
{
private readonly AppConfig _config;
public MyService(IOptions<AppConfig> config)
{
_config = config.Value;
}
}
</pre></div>
<p>2. 用户设置 (WinForms/WPF)</p>
<div class="jb51code"><pre class="brush:csharp;">// 保存设置
Properties.Settings.Default.Theme = "Dark";
Properties.Settings.Default.Save();
// 读取设置
var theme = Properties.Settings.Default.Theme;
</pre></div>
<p><strong>特点</strong></p>
<ul><li>生命周期:持久化到配置文件</li><li>线程安全:内置线程安全</li><li>适用场景:应用程序配置、用户偏好设置</li></ul>
<p class="maodian"><a name="_label2"></a></p><h2>三、依赖注入容器</h2>
<p>ASP.NET Core 示例</p>
<div class="jb51code"><pre class="brush:csharp;">// 注册服务
services.AddSingleton<IGlobalCache, MemoryCache>();
services.AddScoped<IUserSession, UserSession>();
// 使用
public class MyController : Controller
{
private readonly IGlobalCache _cache;
public MyController(IGlobalCache cache)
{
_cache = cache;
}
}
</pre></div>
<p><strong>特点</strong></p>
<p>生命周期:</p>
<ul><li>Singleton: 应用程序生命周期</li><li>Scoped: 请求生命周期</li><li>Transient: 每次请求新实例</li></ul>
<p>线程安全:取决于实现</p>
<p>适用场景:ASP.NET Core 应用、服务共享</p>
<p class="maodian"><a name="_label3"></a></p><h2>四、内存缓存 (IMemoryCache)</h2>
<p>实现方式</p>
<div class="jb51code"><pre class="brush:csharp;">// 注册
services.AddMemoryCache();
// 使用
public class DataService
{
private readonly IMemoryCache _cache;
public DataService(IMemoryCache cache)
{
_cache = cache;
}
public string GetCachedData(string key)
{
return _cache.GetOrCreate(key, entry =>
{
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30);
return ExpensiveDatabaseCall();
});
}
}</pre></div>
<p>特点</p>
<ul><li>生命周期:应用程序重启后丢失</li><li>线程安全:内置线程安全</li><li>适用场景:频繁访问的临时数据</li></ul>
<p class="maodian"><a name="_label4"></a></p><h2>五、分布式缓存 (IDistributedCache)</h2>
<p>实现方式</p>
<div class="jb51code"><pre class="brush:csharp;">// 使用Redis
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "localhost:6379";
});
// 使用
public async Task<byte[]> GetCachedDataAsync(string key)
{
return await _distributedCache.GetAsync(key);
}
</pre></div>
<p><strong>特点</strong></p>
<ul><li>生命周期:持久化到外部存储</li><li>线程安全:内置线程安全</li><li>适用场景:分布式应用、多实例共享数据</li></ul>
<p class="maodian"><a name="_label5"></a></p><h2>六、HttpContext.Items (ASP.NET Core)</h2>
<p>实现方式</p>
<div class="jb51code"><pre class="brush:csharp;">// 中间件中设置
app.Use(async (context, next) =>
{
context.Items["RequestStartTime"] = DateTime.UtcNow;
await next();
});
// 控制器中访问
var startTime = HttpContext.Items["RequestStartTime"] as DateTime?;
</pre></div>
<p><strong>特点</strong></p>
<ul><li>生命周期:单个HTTP请求期间</li><li>线程安全:每个请求独立</li><li>适用场景:请求级数据共享</li></ul>
<p class="maodian"><a name="_label6"></a></p><h2>七、环境变量</h2>
<p>访问方式</p>
<div class="jb51code"><pre class="brush:csharp;">var envVar = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
</pre></div>
<p><strong>特点</strong></p>
<ul><li>生命周期:进程生命周期或系统级</li><li>线程安全:只读操作安全</li><li>适用场景:部署配置、环境特定设置</li></ul>
<p class="maodian"><a name="_label7"></a></p><h2>八、数据库存储</h2>
<p>实现方式</p>
<div class="jb51code"><pre class="brush:csharp;">// 使用EF Core
public class AppDbContext : DbContext
{
public DbSet<GlobalSetting> GlobalSettings { get; set; }
}
// 使用
var setting = await _dbContext.GlobalSettings
.FirstOrDefaultAsync(s => s.Key == "MaintenanceMode");
</pre></div>
<p><strong>特点</strong></p>
<ul><li>生命周期:持久化</li><li>线程安全:取决于数据库访问层</li><li>适用场景:需要持久化的全局配置</li></ul>
<p class="maodian"><a name="_label8"></a></p><h2>九、选择指南</h2>
<table><thead><tr><th>存储方式</th><th>生命周期</th><th>持久化</th><th>分布式支持</th><th>典型使用场景</th></tr></thead><tbody><tr><td>静态成员</td><td>应用程序域</td><td>否</td><td>否</td><td>全局常量、简单缓存</td></tr><tr><td>应用程序配置</td><td>持久化</td><td>是</td><td>部分</td><td>应用设置、用户偏好</td></tr><tr><td>依赖注入容器</td><td>取决于注册类型</td><td>否</td><td>否</td><td>服务共享、全局服务</td></tr><tr><td>内存缓存</td><td>应用程序</td><td>否</td><td>否</td><td>频繁访问的临时数据</td></tr><tr><td>分布式缓存</td><td>持久化</td><td>是</td><td>是</td><td>多实例共享数据</td></tr><tr><td>HttpContext.Items</td><td>请求期间</td><td>否</td><td>否</td><td>请求级数据传递</td></tr><tr><td>环境变量</td><td>进程/系统</td><td>是</td><td>是</td><td>部署配置、环境特定设置</td></tr><tr><td>数据库存储</td><td>持久化</td><td>是</td><td>是</td><td>需要持久化的全局配置</td></tr></tbody></table>
<p class="maodian"><a name="_label9"></a></p><h2>十、最佳实践建议</h2>
<p>1.按需选择:根据数据特性(大小、访问频率、生命周期)选择合适方式</p>
<p>2.分层设计:</p>
<ul><li>高频小数据:内存缓存</li><li>配置数据:appsettings.json</li><li>用户数据:数据库</li></ul>
<p>3.线程安全:</p>
<ul><li>多线程访问时使用线程安全集合(如 ConcurrentDictionary)</li><li>考虑使用 Immutable 集合避免意外修改</li></ul>
<p>4.性能考虑:</p>
<ul><li>大数据集避免使用静态变量</li><li>考虑使用缓存过期策略</li></ul>
<p>5.测试友好:</p>
<ul><li>避免过度使用静态类</li><li>优先使用依赖注入</li></ul>
<p>6.分布式场景:</p>
<ul><li>多服务器环境使用分布式缓存</li><li>考虑使用消息队列同步状态</li></ul>
<p class="maodian"><a name="_label10"></a></p><h2>十一、高级模式示例</h2>
<p class="maodian"><a name="_lab2_10_0"></a></p><h3>混合缓存策略</h3>
<div class="jb51code"><pre class="brush:csharp;">public class HybridCache
{
private readonly IMemoryCache _memoryCache;
private readonly IDistributedCache _distributedCache;
public HybridCache(IMemoryCache memoryCache, IDistributedCache distributedCache)
{
_memoryCache = memoryCache;
_distributedCache = distributedCache;
}
public async Task<T> GetOrCreateAsync<T>(string key, Func<Task<T>> factory, TimeSpan expiration)
{
if (_memoryCache.TryGetValue(key, out T memoryValue))
{
return memoryValue;
}
var distributedValue = await _distributedCache.GetStringAsync(key);
if (distributedValue != null)
{
var value = JsonSerializer.Deserialize<T>(distributedValue);
_memoryCache.Set(key, value, expiration);
return value;
}
var newValue = await factory();
_memoryCache.Set(key, newValue, expiration);
await _distributedCache.SetStringAsync(key,
JsonSerializer.Serialize(newValue),
new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = expiration });
return newValue;
}
}</pre></div>
<p class="maodian"><a name="_lab2_10_1"></a></p><h3>配置热重载</h3>
<div class="jb51code"><pre class="brush:csharp;">// Program.cs
builder.Services.Configure<AppConfig>(builder.Configuration.GetSection("AppConfig"));
builder.Services.AddSingleton<IOptionsMonitor<AppConfig>>(provider =>
provider.GetRequiredService<IOptionsMonitor<AppConfig>>());
// 使用
public class ConfigService
{
private readonly AppConfig _config;
public ConfigService(IOptionsMonitor<AppConfig> configMonitor)
{
_config = configMonitor.CurrentValue;
configMonitor.OnChange(newConfig =>
{
_config = newConfig;
});
}
}</pre></div>
<p>通过合理选择和组合这些全局数据存储方式,可以构建出既高效又易于维护的 .NET 应用程序架构。</p>
頁:
[1]