SqlDataAdapter是否打开自己的连接?

时间:2016-11-16 14:29:09

标签: c# sql sql-server tsql ado.net

SqlDataAdapter是否打开了自己的连接?

        private DataTable UpdateOxa(ProductCatalogSyncData syncDataModel, string connectionString)
    {
        var ds = syncDataModel.SyncDataSet;
        var dtResults = new DataTable("BillingIds");
        var syncConfig = syncDataModel.XDataMapping;
        string EntityName;


        string queryString =
                    @"         
                                IF OBJECT_ID('#CRM2Oxa_ID_MAPPING') IS NOT NULL
                               DROP TABLE #CRM2Oxa_ID_MAPPING


                               CREATE TABLE #CRM2Oxa_ID_MAPPING(
                                [EntityName][nvarchar](1000) NULL,

                                   [TableName][nvarchar](1000) NULL,

                                   [CRMID][uniqueidentifier] NULL,

                                   [OxaID][int] NOT NULL,

                                   [CRMColumnName][nvarchar](1000) NULL
                               ) ";
        var listOfSqlCommands = new List<SqlCommand>();
        var OxaConnection = new SqlConnection(connectionString);

        try
        { 


            OxaConnection.Open();

            using (var createTempTableCommand = new SqlCommand(queryString, OxaConnection))
            {
                createTempTableCommand.ExecuteNonQuery();
            }

                foreach (DataTable dt in ds.Tables)
                {
                    EntityName =
                        StringDefaultIfNull(
                            syncConfig.Root.XPathSelectElement("./entity[@name='" + dt.TableName + "']"),
                            "OxaTableName").Substring(3);

                    var OxaCommand = new SqlCommand();

                    OxaCommand.CommandType = CommandType.StoredProcedure;
                    OxaCommand.CommandText = "Oxa720_P_" + EntityName + "Sync";

                    var entityNameParam = new SqlParameter("@EntityName", dt.TableName);
                    OxaCommand.Parameters.Clear();
                    OxaCommand.Parameters.Add(entityNameParam);
                    var tblParam = new SqlParameter("@O720_" + EntityName, SqlDbType.Structured);
                    tblParam.Value = dt;
                    OxaCommand.Parameters.Add(tblParam);
                    OxaCommand.Connection = OxaConnection;

                    listOfSqlCommands.Add(OxaCommand);
                }



                foreach (var command in listOfSqlCommands)
                {
                    using (var da = new SqlDataAdapter(command))
                    {
                        da.Fill(dtResults);
                    }

                }
        }
        finally
        {
            OxaConnection.Close();
        }
        return dtResults;

    }

我从数据库收到一条消息,表 #temptable 不存在。

SqlDataAdapter是否打开了自己的连接?也许这就是它没有看到本地临时表的原因?

2 个答案:

答案 0 :(得分:3)

来自SqlDataAdapter.Fill()方法的文档:

  

与select命令关联的IDbConnection对象必须有效,但不需要打开。如果在调用Fill之前关闭IDbConnection,则会打开它以检索数据然后关闭。如果在调用Fill之前连接已打开,则它将保持打开状态。

所以我们在这里看到SqlDataAdapter 使用任何特殊的私有连接,但会尝试自动打开你提供的任何连接。

您遇到的问题是.Fill()方法的每次调用都发生在单独的Execution Context 中。

答案 1 :(得分:1)

如果您的SqlConnection已经打开,那么SqlDataAdapter应该按原样使用它(即不关闭/打开它)。

为什么存储过程无法看到临时表的一种可能性是,ADO.NET执行了第一个SqlCommand(用于创建临时表),并使用sp_executesql调用。这意味着临时表在存储的proc sp_executesql的范围内创建,即使您使用相同的连接也不会对后续命令可见。要检查,您可以运行Sql Profiler跟踪 - 如果您看到sp_executesql用于您的第一个SqlCommand,那么您将遇到问题。

此评论于: Sql Server temporary table disappears可能相关:

  

老实说,我认为它与SqlCommand文本的方式有关   结构化的。如果它是一个简单的选择,没有参数,那么它   可以作为一个简单的select语句运行,因此它不会被包装在一个   SqlProcedure喜欢&#39; sp_executesql&#39;,所以它仍然可见   后续查询使用相同的SqlCommand和SqlConnection   宾语。另一方面,如果它是一个复杂的语句,临时表   可以在诸如&#sp ;executesql&#39;之类的存储过程中创建   命令完成时将超出范围。 - Triynko   2月25日&15; 15日21:10

如果ADO.NET确实使用sp_executesql作为表创建命令,那么您可以通过将命令分解为2个SqlCommands来诱使它不使用它:如果临时表存在,则删除临时表,并且另一个只是创建临时表。

编辑:旁注,此代码:

IF OBJECT_ID('#CRM2Oxa_ID_MAPPING') IS NOT NULL
       DROP TABLE #CRM2Oxa_ID_MAPPING

应该是:

IF OBJECT_ID('tempdb..#CRM2Oxa_ID_MAPPING') IS NOT NULL
       DROP TABLE #CRM2Oxa_ID_MAPPING

否则OBJECT_ID('#CRM2Oxa_ID_MAPPING')将始终为null(除非您已经在临时数据库中)。

编辑2 :这里有一些适合我的简单代码:

        DataSet ds = new DataSet();

        using(SqlConnection conn = new SqlConnection("YourConnectionString"))
        {
            conn.Open();

            string str = "if object_id('tempdb..#mytest') is not null drop table #mytest; create table #mytest (id int)";

            // create temp table
            using(SqlCommand cmdc = new SqlCommand(str, conn))
            {
                cmdc.ExecuteNonQuery(); 
            }

            // insert row
            using (SqlCommand cmdi = new SqlCommand("insert #mytest (id) values (1)", conn))
            {
                cmdi.ExecuteNonQuery();
            }

            // use it
            using (SqlCommand cmds = new SqlCommand("dbo.mytestproc", conn))
            {
                cmds.CommandType = CommandType.StoredProcedure;
                cmds.Parameters.Add("@id", SqlDbType.Int).Value = 1;
                cmds.Connection = conn;

                using (SqlDataAdapter da = new SqlDataAdapter(cmds))
                {
                    da.Fill(ds);
                }
            } 

            // clean up - drop temp table
            string strd = "if object_id('tempdb..#mytest') is not null drop table #mytest";
            using (SqlCommand cmdd = new SqlCommand(strd, conn))
            {
                cmdd.ExecuteNonQuery();
            }
        }

        MessageBox.Show("done, num rows " + ds.Tables[0].Rows.Count);

存储过程如下所示:

create proc dbo.mytestproc(@id int)
as
select * from #mytest where id = @id
GO

最后,它显示:&#34; done,num rows 1&#34;