【发布时间】:2012-03-12 04:21:22
【问题描述】:
我正在我的数据库和我的 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。
(旁注 - 缓存层是通用的,所以我不能对密钥的性质和合适的排序规则做出特定的假设。我数据库中的所有表都共享相同的默认服务器排序规则。我只是需要匹配现有的排序规则)
【问题讨论】:
标签: c# .net sql-server collation stringcomparer