3

我有一个 C# 应用程序,使用 ADO.Net 连接到 MSSQL

我需要创建表(具有动态列数),然后插入许多记录,然后从表中进行选择。

每个步骤都必须是一个单独的 C# 调用,尽管我可以在此期间保持连接/事务打开。

4

5 回答 5

6

问题是#Temp 表仅存在于连接和执行范围内。当从 C# 到 SQL 的第一次调用完成时,控制权传递到更高级别的范围。

这就像您有一个调用两个存储过程的 T-SQL 脚本一样。每个 SP 都创建了一个名为#MyTable 的表。第二个 SP 引用的表与第一个 SP 完全不同。
但是,如果父 T-SQL 代码创建了表,则两个 SP 都可以看到它,但彼此看不到。

这里的解决方案是使用##Temp 表。它们跨越范围和联系。但危险在于,如果您使用硬编码名称,那么同时运行的程序的两个实例可能会看到同一张表。因此,动态地将表名设置为始终唯一的名称。

于 2013-02-05T20:03:22.007 回答
6

SQL Server 中有两种临时表,本地临时表和全局临时表。来自 BOL:

本地临时表名称前缀为单号 (#tablename),全局临时表名称前缀为双号 (##tablename)。

本地临时表仅适用于当前的连接。全局变量将可用于所有连接。因此,如果您在相关调用中重复使用(并且您确实说过可以)相同的连接,您可以只使用本地临时表,而不必担心同时进程会干扰彼此的临时表。

您可以从BOL 文章中获得更多信息,特别是在大约一半的“临时表”部分下。

于 2009-08-12T20:49:47.937 回答
1

就在 C# 中处理这个概念而言,您可以查看存储库模式。这允许您拥有一个用于数据访问的低级别存储库层,其中每个方法执行一个任务。但是连接被传递给方法,并且实际操作是在事务范围内执行的。这意味着理论上您可以在数据访问层(作为存储库实现)中调用许多不同的方法,如果其中任何一个方法失败,您可以回滚整个操作。

http://martinfowler.com/eaaCatalog/repository.html

您问题的其他方面将由标准 sql 处理,您可以在其中动态创建表、插入表、从中删除等。这里棘手的部分是使一个事务远离另一个事务。您可能希望使用临时表......或者您可能只是有一个专门用于执行此动态表概念的第二个数据库。

于 2009-08-12T20:37:43.873 回答
0

就我个人而言,我认为您正在以艰难的方式做到这一点。在一个存储过程中执行所有步骤。

于 2009-08-12T21:25:58.457 回答
0

延长单磅符号#Temp 的范围/寿命的一种方法是使用事务。下面我使用的是 Dapper,但您可以了解事务如何使 #temp 表保持活动状态。

    class TestTable1
    {
        public int Col1 { get; set; }
        public string Col2 { get; set; }
    }
    [TestMethod]
    public void TempTableBetweenExecutionsTest()
    {
        using var conn = new SqlConnection(_testDbConnectionString);
        conn.Open();
        var tran = conn.BeginTransaction(IsolationLevel.ReadCommitted);
        conn.Execute("create table #test1(col1 int, col2 varchar(20))", transaction:tran);
        conn.Execute("insert into #test1(col1,col2) values (1, 'one'),(2,'two')", transaction: tran);
        var tableResult =  conn.Query<TestTable1>("select col1, col2 from #test1",transaction:tran).ToList();
        tran.Commit();
    }

TransactionScope 也会给你同样的效果,因为 TransactionScope 在后台创建环境事务。

        [TestMethod]
    public void TempTableBetweenExecutionsScopeTest()
    {
        using var scope = new TransactionScope();
        using var conn = new SqlConnection(_testDbConnectionString);
        conn.Open();

        conn.Execute("create table #test1(col1 int, col2 varchar(20))");
        conn.Execute("insert into #test1(col1,col2) values (1, 'one'),(2,'two')");
        var tableResult = conn.Query<TestTable1>("select col1, col2 from #test1").ToList();
        scope.Complete();
    }
于 2021-03-25T00:13:47.967 回答