如何通过不提交当前会话事务将 DataTable 作为参数传递给存储过程?

Posted

技术标签:

【中文标题】如何通过不提交当前会话事务将 DataTable 作为参数传递给存储过程?【英文标题】:How to pass DataTable as a parameter to Stored Procedure by not commiting the current session transaction? 【发布时间】:2012-04-24 06:20:42 【问题描述】:

我的代码如下所示:

public void InsertSampleData(DataTable tempTable)
    
       session.Transaction.Commit();
        var connection = session.GetSessionImplementation().Connection;
        using (var sqlConnection = (SqlConnection)connection)
        
            using (var cmd = sqlConnection.CreateCommand())
            
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.CommandText = "dbo.insertData";
                cmd.Parameters.Add("@sItems", SqlDbType.Structured);
                var sqlParam = cmd.Parameters["@Items"];
                sqlParam.Direction = ParameterDirection.Input;
                sqlParam.TypeName = "[dbo].[DataItemType]";
                sqlParam.Value = tempTable;
                cmd.ExecuteNonQuery();
            
        
    

代码工作正常,但如果我不提交事务,它会抛出异常,如图所示

System.InvalidOperationException: ExecuteNonQuery 要求命令有一个事务,当连接分配给 命令处于待处理的本地事务中。交易属性 的命令尚未初始化。

但我不希望在完成整个操作之前提交事务。我怎样才能做到这一点??

【问题讨论】:

GetSessionImplementation 返回什么? @Baz1nga 它返回的东西实现了ISession 这是一个休眠的东西 NHibernate.Engine.ISessionImplementor GetSessionImplementation() NHibernate.ISession 的成员 摘要:获取会话实现。返回: NHibernate.Engine.ISessionImplementor 接口的 NHibernate 实现 备注:提供此方法是为了从包装器实现中获取会话的 NHibernate 实现。 NHibernate.ISession 接口的实现者应该返回这个方法的 NHibernate 实现。 【参考方案1】:

问题是应该使用的事务已经提交并且已经被释放,因此要么实例化一个新的 SqlConnection,要么获取一个新会话,然后将查询作为新会话的一部分运行。

public void InsertSampleData(DataTable tempTable)

    session.Transaction.Commit();

    using (var sqlConnection = new SqlConnection(session.GetSessionImplementation()
                                       .Connection.ConnectionString))
    
        using (var cmd = sqlConnection.CreateCommand())
        
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.CommandText = "dbo.insertData";
            cmd.Parameters.Add("@sItems", SqlDbType.Structured);
            var sqlParam = cmd.Parameters["@Items"];
            sqlParam.Direction = ParameterDirection.Input;
            sqlParam.TypeName = "[dbo].[DataItemType]";
            sqlParam.Value = tempTable;
            cmd.ExecuteNonQuery();
        
    

public void InsertSampleData(DataTable tempTable)
    
       session.Transaction.Commit();
        var connection = session.SessionFactory.OpenSession().GetSessionImplementation().Connection;
        using (var sqlConnection = (SqlConnection)connection)
        
            using (var cmd = sqlConnection.CreateCommand())
            
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.CommandText = "dbo.insertData";
                cmd.Parameters.Add("@sItems", SqlDbType.Structured);
                var sqlParam = cmd.Parameters["@Items"];
                sqlParam.Direction = ParameterDirection.Input;
                sqlParam.TypeName = "[dbo].[DataItemType]";
                sqlParam.Value = tempTable;
                cmd.ExecuteNonQuery();
            
        
    

顺便说一句,为什么要使用 SQLConnection 为什么不使用 Nhibernate 会话执行查询,您可以使用 Nhibernate 会话完成您现在正在做的所有事情。

session.CreateSQLQuery(<your sql>)
.SetParameters()   //and various other API to set your parameters
.ExecuteUpdate();

【讨论】:

是的,我尝试过使用 Nhibernate 会话,但是如何将 DataTable 作为参数传递,因为存储过程需要一个表值参数

以上是关于如何通过不提交当前会话事务将 DataTable 作为参数传递给存储过程?的主要内容,如果未能解决你的问题,请参考以下文章

事务如何在 nhibernate 中工作?

如何检查 PostgreSQL 事务中的待处理操作

oracle临时表

如何检查PostgreSQL事务中的挂起操作

如何确认当前事务的隔离级别

mysql 中手动设置事务提交