使用dapper,为什么在一次使用连接时创建的临时表在第二次使用同一连接时不可用

我正在尝试使用C#中的dapper执行一系列SQL * Server步骤。 一步创建一个临时表并填充它。 以下步骤从临时表中查询数据。 create / populate似乎运行成功,但temp表中的第一个查询失败说:

“无效的对象名称’#GetPageOfGlobalUsers’。”

using (SqlConnection connection = DBConnectionProvider.CreateConnection()) { ... misc setup stuff... connection.Execute(@" create table #GetPageOfGlobalUsers(row int, EmailAddress nvarchar(max), LastName nvarchar(max), FirstName nvarchar(max), Id uniqueidentifier) insert into #GetPageOfGlobalUsers SELECT ROW_NUMBER() OVER (order by LastName, FirstName, EmailAddress) row, EmailAddress, LastName, FirstName, Id FROM Users WHERE LastName like @search or FirstName like @search or EmailAddress like @search ", new { search = search } ); int count = connection.Query(@" SELECT count(*) from tempdb..#GetPageOfGlobalUsers ").Single(); ... more queries from the temp table follow 

上面,执行工作,但查询失败,上面提到的错误。 (请注意,无论我是否使用“tempdb ..”前缀,我都会得到相同的错误。)如果我创建了一个永久表(即,如果我删除了前导哈希)或者我将它设为全局临时表(即前缀)有两个哈希的名字)一切正常。

我的理解是,用单个哈希命名的临时表的范围是连接的持续时间,所以我不知道发生了什么。 但我相信有人可以告诉我!

(顺便说一句,如果没有人告诉我“不要这样做”,我会很感激,除非它根本无法完成。)

我不明白到底发生了什么,但是我能够通过在它自己的Execute中创建临时表来解决这个问题,而不是在Execute中创建表并填充它,就像在代码中一样在我的问题中显示。

也就是说,以下工作:

  connection.Execute(@" create table #PagesOfUsers(row int, EmailAddress nvarchar(max), LastName nvarchar(max), FirstName nvarchar(max), Id uniqueidentifier)" ); connection.Execute(@" insert into #PagesOfUsers SELECT ROW_NUMBER() OVER (order by LastName, FirstName, EmailAddress) row, EmailAddress, LastName, FirstName, Id FROM Users WHERE LastName like @search or FirstName like @search or EmailAddress like @search ", new { search = search } ); int count = connection.Query(@" SELECT count(*) from #PagesOfUsers ").Single(); 

这并不可怕,但不方便。 值得注意的是,我根本不必显式创建临时表。 实际上,我最初将create / populate操作编码为SELECT INTO,因此我没有必须逐条列出临时表的列。 但是在后续查询中也遇到了“无效对象”错误,因此我尝试使用显式CREATE TABLE来查看它是否有所不同,并在发现它没有发现我的问题。

我看到的行为是,当创建临时表并在同一个Execute中填充时,它在Execute结束后确实不在tempdb中,表面上是成功的。 这让我想知道我的原始代码中的Execute是否正在做任何事情! 据我所知,这相当于NOOP。

我怀疑连接没有打开。 如果是这样,dapper将根据需要打开和关闭(返回池)连接。 这将重置连接,丢失命令之间的任何临时表。

只需明确打开连接。

以下对我来说非常适合:

 db.Open(); db.Execute( @"create table #foo (val int not null); insert #foo (val) values (123)"); db.Execute( @"insert #foo (val) values (456)"); var vals = db.Query( @"select * from #foo").ToList(); foreach(var val in vals) Console.WriteLine(val); 

如果我使用它也可以完美地工作:

 @"select * from tempdb..#foo" 

根据我之前的回答,我可以让它停止工作的唯一方法是不先打开连接