我正在我的数据库和我的 C# 代码之间实现一个缓存层。这个想法是根据查询的参数缓存某些数据库查询的结果。数据库使用默认排序规则 -SQL_Latin1_General_CP1_CI_AS
或Latin1_General_CI_AS
,基于一些简短的谷歌搜索,我相信它等同于相等,只是排序不同。
我需要一个 .NET StringComparer,它可以给我相同的行为,至少对于相等性测试和哈希码生成,因为数据库的排序规则正在使用。目标是能够在 C# 代码中使用 .NET 字典中的 StringComparer 来确定特定的字符串键是否已经在缓存中。
一个非常简单的例子:
var comparer = StringComparer.??? // What goes here?
private static Dictionary<string, MyObject> cache =
new Dictionary<string, MyObject>(comparer);
public static MyObject GetObject(string key) {
if (cache.ContainsKey(key)) {
return cache[key].Clone();
} else {
// invoke SQL "select * from mytable where mykey = @mykey"
// with parameter @mykey set to key
MyObject result = // object constructed from the sql result
cache[key] = result;
return result.Clone();
}
}
public static void SaveObject(string key, MyObject obj) {
// invoke SQL "update mytable set ... where mykey = @mykey" etc
cache[key] = obj.Clone();
}
StringComparer 与数据库的排序规则匹配很重要的原因是误报和漏报都会对代码产生不良影响。
如果 StringComparer 说当数据库认为两个键 A 和 B 是不同的时它们是相等的,那么数据库中可能有两行具有这两个键,但是如果要求 A 和B 连续 - 因为 B 的 get 将错误地命中缓存并返回为 A 检索的对象。
如果 StringComparer 在数据库认为 A 和 B 相等的情况下说 A 和 B 是不同的,那么问题就更加微妙了,但问题同样如此。两个键的 GetObject 调用都可以,并返回对应于同一数据库行的对象。但是随后使用键 A 调用 SaveObject 会使缓存不正确;对于具有旧数据的键 B,仍然会有一个缓存条目。随后的 GetObject(B) 将提供过时的信息。
因此,为了使我的代码正常工作,我需要 StringComparer 来匹配数据库行为以进行相等性测试和哈希码生成。到目前为止,我的谷歌搜索已经产生了很多关于 SQL 排序规则和 .NET 比较并不完全等价的信息,但没有详细说明差异是什么,它们是否仅限于排序差异,或者是否有可能找到如果不需要通用解决方案,则等效于特定SQL 排序规则的 StringComparer。
(旁注 - 缓存层是通用的,所以我不能对密钥的性质和排序规则是否合适做出特别的假设。我数据库中的所有表共享相同的默认服务器排序规则。我只需要匹配存在的排序规则)