我正在尝试优化旧应用程序,现在我正在尝试将SQL请求降至最低。 我已经创建了简单的缓存机制,但它需要3种方法:
public static List<Models.CarModel> GetCarModels()
{
return GetCarModels(false);
}
public static List<Models.CarModel> GetCarModels(bool reload)
{
const string my_key = "GetCarModels";
object list = HttpContext.Current.Cache[my_key] as List<Models.CarModel>;
if ((reload) || (list == null))
{
list = GetCarModels_P();
HttpContext.Current.Cache.Insert(my_key, list, null, DateTime.Now.AddHours(1), TimeSpan.Zero);
}
return (List<Models.CarModel>)list;
}
private static List<Models.CarModel> GetCarModels_P()
{
var tmp_list = new List<Models.CarModel>();
using (var conn = new SqlConnection())
{
conn.ConnectionString = ConfigurationManager.ConnectionStrings["HelpDesk"].ToString();
using (var cmd = new SqlCommand(@"SELECT_CAR_MODELS", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 360;
conn.Open();
using (SqlDataReader sdr = cmd.ExecuteReader())
{
while (sdr.Read())
{
var carModel = new Models.CarModel()
{
Id = Convert.ToInt32(sdr["Id"]),
Name= Convert.ToString(sdr["CarName"])
};
tmp_list.Add(carModel );
}
}
conn.Close();
}
}
return tmp_list;
}
这很好用,sql查询结果缓存了1个小时,但是对于每个旧方法我必须创建3个新的,所以对于10个旧方法我必须写30个新的。
我想减少必须编写的代码数量,可能有一种方法可以创建读取/写入缓存的通用方法。
GetCarModels_P
可能不会改变,但我可以优化我的两种公共方法(I quess)。
答案 0 :(得分:1)
您可以使用泛型和lambda来简化您的更改:
public static List<T> GetViaCache<T>(bool reload, string key, Func<List<T>> loader)
{
object list = HttpContext.Current.Cache[key] as List<T>;
if ((reload) || (list == null))
{
list = loader();
HttpContext.Current.Cache.Insert(key, list, null, DateTime.Now.AddHours(1), TimeSpan.Zero);
}
return list;
}
这将加载代码简化为
public static List<Models.CarModel> GetCarModels(bool reload)
{
return GetViaCache<Models.CarModel>(reload, "GetCarModels", GetCarModels_P);
}
当然,您仍然需要为缓存生成唯一的密钥。
答案 1 :(得分:1)
您可以在辅助类中实现该模式,如下所示:
internal class Cached<T> where T: class
{
private readonly Func<T> _loadFunc;
private readonly string _key;
private readonly TimeSpan _expiration;
public Cached(Func<T> loadFunc, string key, TimeSpan expiration)
{
_loadFunc = loadFunc;
_key = key;
_expiration = expiration;
}
public T GetValue(bool reload)
{
T value = (T)HttpContext.Current.Cache[_key];
if (reload || value == null)
{
value = _loadFunc();
HttpContext.Current.Cache.Insert(_key, value, null,
DateTime.Now + _expiration, TimeSpan.Zero);
}
return value;
}
}
你会这样使用它:
private static Cached<List<Models.CarModel>> _carModels =
new Cached<List<Models.CarModel>>(
GetCarModels_P, "GetCarModels", TimeSpan.FromHours(1));
public static List<Models.CarModel> GetCarModels()
{
return _carModels.GetValue(false);
}
当然,您也可以只使用通用方法(就像我写这篇文章时发布的其他答案之一)。这取决于我将使用的情况。如果你有类似的强制重新加载的调用,我的方法会更容易,因为你不必重复自己。但是,在不利方面,我的实现有点暗示Cached
实例本身保留了数据,而实际上是HttpContext缓存这样做。
答案 2 :(得分:0)
您刚刚写了两个非常好的理由,说明为什么要使用像NHibernate或Entity Framework这样的ORM层。他们带走了痛苦,编写了大量的样板SQL调用函数。他们支持缓存,我知道这很简单,就像NH一样,不确定EF。
不需要丢弃任何现有代码,ORM可以与您现有的数据库代码共存,甚至可以使用完全相同的连接。您可以逐个迁移现有功能,从无法使用的SQL迁移到您选择的ORM。如果您想花时间优化旧应用,我会说这是花时间的最佳方式。