我正在为某些项目的 SQL Server 创建可重用的数据访问层。我在寻找将 .NETdecimal
作为参数传递给查询的正确方法时遇到问题。最明显的方式:
cmd.Parameters.AddWithValue("@P0", parameterValue);
效果几乎很好。该值已正确存储在 DB 中,但 SqlClient 从实际值推断出确切的类型,因此当应用程序传递 12345.678 时,它会将 @P0 声明为NUMERIC(8,3)
. 当完全相同的查询与其他值一起使用时,将声明该值的精度和比例。由于我不知道的原因,从 SQL Server 中,这些查询不相等,并且每个查询都在sys.dm_exec_cached_plans
. 存在完全相同的问题string
- 对于每个长度都有不同的查询计划。
我们的一些应用程序每分钟写入相当多的记录,每个记录有 5-10 个decimal
值,范围变化很大(一些传感器数据,一些货币值)。几乎每个INSERT
人都有自己的查询计划,一天后缓存了超过 10 万个相同查询计划的版本,占用了几 GB 的 RAM。
我要处理的想法是将所有可能的类型合并为一些任意选择的类型。对于decimal
,当精度低于 20 时,我将其设置为 20。当精度大于 20 时,我将其设置为比实际精度大的可被 4 整除的最小值(例如 24、28、32、36)。音阶(最小 2,然后是 2)和弦乐(最小 128,然后是 2 的幂)也是如此。这种方式似乎可以控制问题 - 我已经看到每个查询有大约 100 个计划变体,而不是 100k,并且 SQL Server 将内存用于缓冲池,而不是用于一些无用的计划。
这种方法有什么可能出错的吗?在使用 SqlClient 和加载的查询时,是否有更好的方法来控制查询计划缓存decimals
?
我不能做的事情清单:
- 使用存储过程——因为这个 DAL 的目的是为许多 DBMS(目前是 SQL Server、MS Access、Firebird、Oracle)创建抽象层。
- 强迫我的队友以某种方式传递每个变量的实际类型——因为那太残忍了。
- 删除这个 DAL,使用普通的旧 DbProviderFactory 并创建像 1990 年那样的参数 - 因为这个 DAL 还处理 SQL 方言的查询创建、数据库结构创建等。
- 丢弃这个 DAL 并使用像 NHibernate 这样的“正确”DAO - 因为它不是在这里发明的。
- 将此问题提交给 dba.stackexchange.com - 因为这是 SqlClient 和我使用它的方式的问题,而不是 SQL Server 本身的问题。