.NET泛型Repository如何避免重复生成SQL字符串?
解决方案
你的核心问题是瞬态作用域的泛型Repository每次实例化都会重复生成相同类型T对应的SQL,因为同一泛型封闭类型(如SomeRepository<User>)的SQL逻辑固定,无需每次实例化都重新计算。以下是两种高效的解决方式:
方案1:静态泛型字段 + 静态构造函数(推荐)
利用CLR对泛型类型的特性:每个封闭泛型类型(如SomeRepository<User>、SomeRepository<Order>)会拥有独立的静态成员,且静态构造函数对每个封闭类型仅执行一次,天然实现线程安全的单例缓存。
public class SomeRepository<T> { // 每个封闭泛型类型独享的静态缓存字段 private static readonly string _cachedSql; private readonly string _sql; // 静态构造函数:首次创建该泛型类型实例时执行一次 static SomeRepository() { _cachedSql = BuildSqlForType(); } public SomeRepository() { // 直接复用已缓存的SQL _sql = _cachedSql; } private static string BuildSqlForType() { // 这里编写基于T生成SQL的逻辑,示例: var tableName = typeof(T).Name; return $"SELECT * FROM {tableName}"; } public IEnumerable<T> Read() { // 使用_sql执行查询 // ... } }
优势:
- 无需手动管理缓存键和线程安全,CLR自动处理
- 代码简洁,缓存逻辑与业务逻辑分离
方案2:全局ConcurrentDictionary缓存(灵活扩展)
如果需要手动控制缓存生命周期(比如后续要清理特定类型的缓存),可以使用线程安全的ConcurrentDictionary作为全局缓存容器:
public class SomeRepository<T> { // 全局缓存容器,键为实体类型,值为对应SQL private static readonly ConcurrentDictionary<Type, string> _sqlCache = new ConcurrentDictionary<Type, string>(); private readonly string _sql; public SomeRepository() { // GetOrAdd:若缓存中无该类型的SQL则生成并缓存,否则直接返回缓存值 _sql = _sqlCache.GetOrAdd(typeof(T), GenerateSql); } private string GenerateSql(Type entityType) { // 基于T生成SQL的逻辑,示例: var tableName = entityType.Name; return $"SELECT * FROM {tableName}"; } public IEnumerable<T> Read() { // 使用_sql执行查询 // ... } }
优势:
- 支持手动操作缓存(如调用
_sqlCache.TryRemove清理特定类型的SQL) - 适合多组件共享SQL缓存的场景
内容的提问来源于stack exchange,提问作者Zenith
相关产品推荐
相关产品推荐

