I solved a previous problem (how to add a hint in NHibernate) but partially. My code adds the with(nolock) to almost every query, all but LINQ. What is wrong with it ?
Code:
public class MsSQLWithNoLockDialect : NHibernate.Dialect.MsSql2005Dialect
{
public MsSQLWithNoLockDialect() {
}
private bool NeedsLockHint(LockMode lockMode) {
return true;
}
public override string AppendLockHint(LockMode lockMode, string tableName) {
if (lockMode.GreaterThan(LockMode.Read)) {
return tableName + " with (updlock, rowlock)";
}
return tableName + " with(nolock)";
}
private struct LockHintAppender
{
private readonly MsSQLWithNoLockDialect dialect;
private readonly IDictionary<string, LockMode> aliasedLockModes;
public LockHintAppender(MsSQLWithNoLockDialect dialect, IDictionary<string, LockMode> aliasedLockModes) {
this.dialect = dialect;
this.aliasedLockModes = aliasedLockModes;
}
public string ReplaceMatch(Match match) {
string alias = match.Groups[1].Value;
string lockHint = dialect.AppendLockHint(aliasedLockModes[alias], alias);
return string.Concat(" ", lockHint, match.Groups[2].Value);
}
}
public override SqlString ApplyLocksToSql(SqlString sql, IDictionary<string, LockMode> aliasedLockModes, IDictionary<string, string[]> keyColumnNames) {
// Regex matching any alias out of those given. Aliases should contain
// no dangerous characters (they are identifiers) so they are not escaped.
string aliasesPattern = StringHelper.Join("|", aliasedLockModes.Keys);
// Match < alias >, < alias,>, or < alias$>, the intent is to capture alias names
// in various kinds of "FROM table1 alias1, table2 alias2".
Regex matchRegex = new Regex(" (" + aliasesPattern + ")([, ]|$)");
SqlStringBuilder result = new SqlStringBuilder();
MatchEvaluator evaluator = new LockHintAppender(this, aliasedLockModes).ReplaceMatch;
foreach (object part in sql.Parts) {
if (part == Parameter.Placeholder) {
result.Add((Parameter)part);
continue;
}
result.Add(matchRegex.Replace((string)part, evaluator));
}
return result.ToSqlString();
}
public override JoinFragment CreateOuterJoinFragment() {
return new ANSIWithNoLockJoinFragment();
}
}
Its simple to understand, but I can't find a way to make it work !
I'm using linq-to-nhibernate !
Thanks !