SqlDataAdapter 是否打开自己的连接?
Does SqlDataAdapter open its own connection?
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;
}
我从数据库收到一条消息,指出 table #temptable 不存在。
SqlDataAdapter 是否打开自己的连接? 也许这就是它看不到本地临时文件的原因table?
来自 SqlDataAdapter.Fill()
方法的文档:
The IDbConnection
object associated with the select command must be valid, but it does not need to be open. If the IDbConnection
is closed before Fill is called, it is opened to retrieve data and then closed. If the connection is open before Fill is called, it remains open.
所以我们在这里看到 SqlDataAdapter 不 使用任何特殊的专用连接,但会尝试自动打开您提供的任何连接。
您在这里遇到的问题是每次调用 .Fill()
方法都发生在 单独的 Execution Context.
中
如果您的 SqlConnection 已经打开,那么 SqlDataAdapter 应该按原样使用它(即没有 closing/opening 它)。
关于为什么您的存储过程无法看到临时文件 table 的一种可能性是 ADO.NET 执行了您的第一个 Sql 命令(用于创建临时文件 table ),通过 sp_executesql 调用。这意味着临时 table 是在存储过程 sp_executesql 的范围内创建的,并且对后续命令不可见,即使您使用的是相同的连接。要检查,您可以 运行 Sql Profiler 跟踪 - 如果您看到 sp_executesql 被用于您的第一个 Sql 命令,那么您就会遇到问题。
此评论位于:
Sql Server temporary table disappears 可能相关:
I honestly think it has to do with the way the SqlCommand text is
structured. If it's a simple select into, with no parameters, then it
may be run as a simple select statement, so it won't be wrapped in an
SqlProcedure like 'sp_executesql', so it will remain visible to
subsequent queries using that same SqlCommand and SqlConnection
object. On the other hand, if it's a complex statement, the temp table
may be created within a stored procedure like 'sp_executesql', and
will go out of scope by the time the command is finished. – Triynko
Feb 25 '15 at 21:10
如果 ADO.NET 确实将 sp_executesql 用于您的 table 创建命令,那么您可以通过将命令分解为 2 Sql命令:一个删除临时 table(如果存在),另一个只创建临时 table。
EDIT :附带说明,此代码:
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')
将始终为空(除非您已经在临时数据库中)。
编辑 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
最后显示:"done, num rows 1"
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;
}
我从数据库收到一条消息,指出 table #temptable 不存在。
SqlDataAdapter 是否打开自己的连接? 也许这就是它看不到本地临时文件的原因table?
来自 SqlDataAdapter.Fill()
方法的文档:
The
IDbConnection
object associated with the select command must be valid, but it does not need to be open. If theIDbConnection
is closed before Fill is called, it is opened to retrieve data and then closed. If the connection is open before Fill is called, it remains open.
所以我们在这里看到 SqlDataAdapter 不 使用任何特殊的专用连接,但会尝试自动打开您提供的任何连接。
您在这里遇到的问题是每次调用 .Fill()
方法都发生在 单独的 Execution Context.
如果您的 SqlConnection 已经打开,那么 SqlDataAdapter 应该按原样使用它(即没有 closing/opening 它)。
关于为什么您的存储过程无法看到临时文件 table 的一种可能性是 ADO.NET 执行了您的第一个 Sql 命令(用于创建临时文件 table ),通过 sp_executesql 调用。这意味着临时 table 是在存储过程 sp_executesql 的范围内创建的,并且对后续命令不可见,即使您使用的是相同的连接。要检查,您可以 运行 Sql Profiler 跟踪 - 如果您看到 sp_executesql 被用于您的第一个 Sql 命令,那么您就会遇到问题。
此评论位于: Sql Server temporary table disappears 可能相关:
I honestly think it has to do with the way the SqlCommand text is structured. If it's a simple select into, with no parameters, then it may be run as a simple select statement, so it won't be wrapped in an SqlProcedure like 'sp_executesql', so it will remain visible to subsequent queries using that same SqlCommand and SqlConnection object. On the other hand, if it's a complex statement, the temp table may be created within a stored procedure like 'sp_executesql', and will go out of scope by the time the command is finished. – Triynko Feb 25 '15 at 21:10
如果 ADO.NET 确实将 sp_executesql 用于您的 table 创建命令,那么您可以通过将命令分解为 2 Sql命令:一个删除临时 table(如果存在),另一个只创建临时 table。
EDIT :附带说明,此代码:
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')
将始终为空(除非您已经在临时数据库中)。
编辑 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
最后显示:"done, num rows 1"