【发布时间】:2014-09-09 22:51:29
【问题描述】:
我有很多来自实体框架拦截器的 SQL 命令,例如:
UPDATE [dbo].[Products]
SET [Name] = @0
WHERE ([Id] = @1)
如何确定该命令是UPDATE 命令?
我写了以下正则表达式:
(update)? [a-z0-9-]+ (set)
但它不支持多行命令且命令文本应为一行,并且不支持表名中带有模式和[]字符的表名。
只支持简单的SQL命令如下:
UPDATE Products SET [Name] = @0 WHERE ([Id] = @1)
注意:
我正在使用实体框架的这个正则表达式和IDbCommandInterceptor 功能为UPDATE 命令向SQL 服务器提供WITH (ROWLOCK) 表提示,所以我需要一个从UPDATE 关键字到SET 关键字的正则表达式,因为@987654331 @ 应该插入到 SET 关键字之前。
考虑以下代码:
String updateCommandRegularExpression = "(update)? [a-z0-9-]+ (set)";
Boolean isUpdateCommand = Regex.IsMatch(commandText, updateCommandRegularExpression, RegexOptions.IgnoreCase | RegexOptions.Multiline); // You may use better regular expression pattern here.
if (isUpdateCommand)
{
Boolean isSnapshotIsolationTransaction = sqlCommand.Transaction != null && sqlCommand.Transaction.IsolationLevel == IsolationLevel.Snapshot;
// Transactions with Snapshot isolation level have more complicated table hints to enable rowlock.
String tableHintToAdd = isSnapshotIsolationTransaction ? " with (rowlock , updlock) set " : " with (rowlock) set ";
commandText = Regex.Replace(commandText, updateCommandRegularExpression, (match) =>
{
return Regex.Replace(match.Value, " SET ", tableHintToAdd, RegexOptions.IgnoreCase); // You may use better regular expression here.
}, RegexOptions.IgnoreCase | RegexOptions.Multiline);
command.CommandText = commandText;
}
【问题讨论】:
-
为什么需要这样做?
-
锁定行而不是锁定整个表,当您只更新几条记录时,有几个性能优势,因为其他事务将继续在同一个表的其他记录上工作没有更新,所以我们等待的交易会更少。
标签: c# sql regex entity-framework