Я реализую уровень кэширования между моей базой данных и моим кодом C #. Идея состоит в том, чтобы кэшировать результаты определенных запросов к БД на основе параметров запроса. В базе данных используется сопоставление по умолчанию - либо SQL_Latin1_General_CP1_CI_AS
, либо Latin1_General_CI_AS
, которые, как я полагаю, на основе небольшого поиска в Google эквивалентны для равенства, но отличаются для сортировки.
Мне нужен.NET StringComparer, который может дать мне такое же поведение, по крайней мере, для проверки равенства и генерации хэш-кода, которое используется при сортировке базы данных. Цель состоит в том, чтобы иметь возможность использовать StringComparer в словаре .NET в коде C #, чтобы определить, находится ли конкретный строковый ключ уже в кеше или нет.
Действительно упрощенный пример:
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 последовательно - потому что get для B неправильно попадет в кеш и вернет объект, который был получен для A.
Проблема более тонкая, если StringComparer говорит, что A и B различны, когда база данных считает, что они равны, но не менее проблематичны. Вызов GetObject для обоих ключей подойдет и вернет объекты, соответствующие одной и той же строке базы данных. Но затем вызов SaveObject с ключом A приведет к неправильному кешированию; для ключа B по-прежнему будет запись в кэше со старыми данными. Последующий GetObject (B) предоставит устаревшую информацию.
Итак, чтобы мой код работал правильно, мне нужен StringComparer, чтобы он соответствовал поведению базы данных при проверке равенства и генерации хэш-кода. Мой поиск в Google дал много информации о том, что сопоставления SQL и.NET-сравнения не совсем эквивалентны, но нет подробностей о том, в чем заключаются различия, ограничиваются ли они только различиями в сортировке или можно ли найти StringComparer, который эквивалентен специфичному сопоставлению SQL, если универсальное решение не требуется.
(Боковое примечание - уровень кэширования является универсальным, поэтому я не могу делать конкретных предположений о природе ключа и подходящем сопоставлении. Все таблицы в моей базе данных используют одинаковое сопоставление серверов по умолчанию. Я просто необходимо сопоставить существующее сопоставление)