使用 C# 和一个连接在 SQL 命令中持久化变量

Posted

技术标签:

【中文标题】使用 C# 和一个连接在 SQL 命令中持久化变量【英文标题】:Persist variables in SQL commands using C# and one connection 【发布时间】:2020-11-26 01:49:21 【问题描述】:

所以也许有人可以指出我正确的方向。

我有一个 .NET 应用程序正在运行的大量 SQL 查询(我将尽力解释,因为我无法发布代码)。

我决定做的是分解查询,这样数据库就不会出现死锁。

长话短说有没有办法保留所有变量

Declare @sometable as Table

因为每个SqlCommand 都需要它之前的查询中的信息和 ID。

这是使用相同的连接。我已经在这工作了 4 天了,我的头在转动。

这是我尝试使用相同命令并更改查询文本的一些代码

foreach (var query in querys)

 command.CommandText = query;
 DataSet ds = new DataSet();
  try 
var reader = command.ExecuteReader();

while (!reader.IsClosed)
ds.Tables.Add().Load(reader);
mergedResults.Add(ds);
 

编辑:这里是需要在每个地方使用的大量查询的顶部示例

DECLARE @dbID int;
DECLARE @idDomain int;
DECLARE @DomainName varchar(255);

DECLARE @IdDrivers TABLE
(
 idDriver int,
 startTime datetime,
 endTime dateTime
);

【问题讨论】:

您需要在问题/代码中提供更多详细信息。您是否希望在后续查询中使用一个查询的结果?或者您有一些想要跨查询重用的参数?您可以考虑使用实体框架(或其他 ORM)并将子查询移动到您的 C# 代码中 我希望我可以使用一个 orm,但写信的人确实试图重新发明***,现在我们被困住了。从技术上讲,我需要的只是参数和一些子查询将信息插入临时表以使用它们甚至更低。原始查询是一个 20k 行代码,带有选择声明等... 当然,google sql server 表变量和临时表.. 并决定哪个最适合您。听起来它也需要捆绑到一个 sproc 中 主要问题是所有这些临时变量都是动态的 @Jonathan 通常不需要将其设为全局;全局变量无法扩展 【参考方案1】:

任何以@ 开头的东西(局部变量、参数、表值参数等)都被限定为单个 SQL 批处理,所以不:它们不能在批处理之间持久化。 # 临时表的范围是连接,但这听起来不是一个好的解决方案。放慢速度并不会改变死锁行为,因为锁定语义是每个操作,而不是每个批次 - 除非您有一个跨越事务,在这种情况下 会产生影响。无论哪种方式:批次数量都不是决定因素。

如果您遇到死锁,您需要调查其原因和原因。使用UPDLOCK 执行一些读取(随后更新相同数据)可能会有所帮助,因为可以更快地获取独占锁。

【讨论】:

【参考方案2】:

如果你想跨批次持久化你的表变量:

您可以使用临时表 (#IdDrivers),而不是表变量 @IdDrivers。在您的第一批中创建此临时表。

例如:

if object_id('tempdb..#IdDrivers') is not null drop table #IdDrivers

create table #IdDrivers (your required columns here)

然后您的第二批可以填充临时表,后续批次可以从中读取。

这应该可以,只要你在第一批之前打开Sql连接,并在最后一批执行后关闭它。

您可能想要创建另一个#temp 表来存储您的变量,例如:@idDomain。

重要的是,创建临时表的批处理不能在后台通过 sp_executesql 执行 - 否则,由于范围限定,您的后续批处理将无法看到您创建的临时表。例如如果您尝试传递参数,那么 ADO.NET 将在后台使用 sp_executesql,因此不要将参数传递给创建临时表的 sql。

【讨论】:

如果我愿意但表中的变量,那么我将不得不修改后续查询以从表中读取。

以上是关于使用 C# 和一个连接在 SQL 命令中持久化变量的主要内容,如果未能解决你的问题,请参考以下文章

如何将数据库查询结果放入变量中

需要有关在 asp.net C# 中使用的 sql 连接的信息

行为类似于线程的 C# 可重用或持久任务

来自 C# 的 SQL 无服务器命令

服务器端的持久数据

在 C# 中使用 Dapper 将数据发送到 RECORD 类型的 PL/SQL 脚本变量会更好吗