我正在学习nHibernate和特定会话,因为我遇到了nHibernate不支持SetParameter()方法中的表值参数的问题。遗憾的是,这是一个问题,因为我有一个存储过程,旨在获取一个表值参数。搜索堆栈溢出时,我遇到了一些涉及此问题的其他问题,这些问题详细说明了使用来自ISession的连接来使用ADO.NET执行操作。 (以下链接)
使用这个我把以下代码放在一起。该方法采用Guids列表,并且应该返回设备GUID的过滤列表。
var myTable = new DataTable("dbo.EntityIds");
var dataset = new DataSet();
myTable.Columns.Add("deviceId", typeof (Guid));
foreach (Guid deviceId in deviceIds)
{
myTable.Rows.Add(deviceId);
}
var con = Session.SessionFactory.OpenSession().GetSessionImplementation().Connection;
using (var sqlConnection = (SqlConnection) con)
{
using (var cmd = sqlConnection.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "dbo.GetLastCommunicationStatus";
cmd.Parameters.Add("@DeviceTableVar", SqlDbType.Structured);
var sqlParam = cmd.Parameters["@DeviceTableVar"];
sqlParam.Direction = ParameterDirection.Input;
sqlParam.TypeName = "[dbo].[EntityIds]";
sqlParam.Value = myTable;
var adapt = new SqlDataAdapter();
adapt.SelectCommand = cmd;
adapt.Fill(dataset);
}
}
deviceFailureList =
dataset.Tables[0].AsEnumerable().Select(dataRow => dataRow.Field<Guid>("deviceId")).ToList();
我在这种情况下最终要问的问题是刚刚开放的Session会发生什么?
另外,有没有办法传递我可能错过的表值参数?我知道由于SetParameters()方法不支持tabled参数,以下内容不起作用:
session.CreateSQLQuery(...)
.SetParameters(...) //and various other API to set your parameters
.ExecuteUpdate();
我还没有尝试过的唯一一件事就是......
using(ITransaction transaction = session.BeginTransaction())
{
…NHibernate stuff…
IDbCommand command = new SqlCommand();
command.Connection = session.Connection;
transaction.Enlist(command);
command.CommandText = “delete from User where clue is null”;
command.ExecuteNonQuery();
…more NHibernate stuff…
}
最终的代码段来自此博客条目:
enlisting ADO commands in NHibernate
是否可以让事务对象登记SqlCommand而不是IDbCommand?我问的原因是,在我的第一个代码片段中,我正在分配一个DataTable参数,并且看起来我不能使用IDbCommand这样做。
更新:
所以我设法让代码使用ITransaction对象的Enlist()方法。下面给出的例子......
using (ITransaction trans = Session.BeginTransaction())
{
SqlCommand unboxed = new SqlCommand();
unboxed.CommandType = CommandType.StoredProcedure;
unboxed.Connection = (SqlConnection)Session.Connection;
unboxed.CommandText = "dbo.GetLastCommunicationStatus";
unboxed.Parameters.Add("@DeviceTableVar", SqlDbType.Structured);
var sqlParam = unboxed.Parameters["@DeviceTableVar"];
sqlParam.Direction = ParameterDirection.Input;
sqlParam.TypeName = "[dbo].[EntityIds]";
sqlParam.Value = myTable;
IDbCommand cmd = unboxed;
trans.Enlist(cmd);
var adapt = new SqlDataAdapter();
adapt.SelectCommand = (SqlCommand)cmd;
adapt.Fill(dataset);
}
我之前的不确定性主要是将SqlCommand的拆箱和装箱作为IDbCommand。但是,上述确实似乎有效。