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是否打开了自己的连接?也许这就是它没有看到本地临时表的原因?
答案 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;