SqlDbType.Structured 在 NHibernate 中传递表值参数以选择不带:param?
Posted
技术标签:
【中文标题】SqlDbType.Structured 在 NHibernate 中传递表值参数以选择不带:param?【英文标题】:SqlDbType.Structured to pass Table-Valued Parameters in NHibernate to select without a :param? 【发布时间】:2017-02-14 14:05:46 【问题描述】:我想将一组 ID(通过表值参数)传递给 NHibernate IQuery
select
语句以在连接中使用:
在本机 SQL 中,我可以做到这一点(下面的 SQLSelectData)。注意SqlCommand
sql 中没有:param
:
public static bool SQLSelectData()
string conACME = System.Configuration.ConfigurationManager
.AppSettings["conACME"].ToString();
DataTable tblBusUnit = new DataTable();
tblBusUnit.Columns.Add("VALUE", typeof(int));
DataRow dRow = tblBusUnit.NewRow();
dRow["Value"] = 1;
tblBusUnit.Rows.Add(dRow);
dRow = tblBusUnit.NewRow();
dRow["Value"] = 6;
tblBusUnit.Rows.Add(dRow);
using (SqlConnection con = new SqlConnection(conACME))
con.Open();
SqlDataReader rdr;
SqlCommand cmd = new SqlCommand(
"select bus_unit_id, BusUnit " +
"from BusUnit b " +
"join @tvpBusUnit s on s.value = b.BUS_UNIT_ID;",
con);
cmd.Parameters.Add(
new SqlParameter()
ParameterName = "@tvpBusUnit",
SqlDbType = SqlDbType.Structured,
TypeName = "dbo.[DLTableTypeInt]",
Value = tblBusUnit
);
rdr = cmd.ExecuteReader();
while (rdr.Read())
string stBusUnitId = rdr["bus_unit_id"].ToString();
string strBusUnit = rdr["BusUnit"].ToString();
Console.WriteLine("Bus Unit:" + strBusUnit);
return true;
我如何在 NHibernate 中执行此操作?我使用Sql2008Structured
和Structured2008Extensions
类尝试了this question 的公认解决方案。
查看下面调用SetStructured()
的代码:
public void SQLSelectTVP<T>()
objNSession = NHibernateHelper.GetCurrentSession(strConn);
DataTable tblBusUnit = new DataTable();
tblBusUnit.Columns.Add("VALUE", typeof(int));
DataRow dRow = tblBusUnit.NewRow();
dRow["Value"] = 1;
tblBusUnit.Rows.Add(dRow);
dRow = tblBusUnit.NewRow();
dRow["Value"] = 6;
tblBusUnit.Rows.Add(dRow);
StringBuilder sbSQL = new StringBuilder();
sbSQL.Length = 0;
sbSQL.Append("select bus_unit_id, Business_Unit " +
"from tblBUSINESS_UNIT b " +
"join @tvpBusUnit s on s.value = b.BUS_UNIT_ID");
IQuery sqlQuery = objNSession.CreateSQLQuery(sbSQL.ToString());
sqlQuery.SetStructured("tvpBusUnit", tblBusUnit);
var lstQR = sqlQuery.List<T>();
但是,由于 SQL 中没有:param
,所以出错:
参数 tvpBusUnit 不作为命名参数存在 [select bus_unit_id, Business_Unit from tblBUSINESS_UNIT b join @tvpBusUnit s on s.value = b.BUS_UNIT_ID]
我该如何解决这个问题?
【问题讨论】:
你想做什么?我不确定“sqlcommand sql 中没有 :param”是什么意思。 看下面粗体的错误信息。 您是否尝试将@
放入sqlQuery.SetStructured("tvpBusUnit", tblBusUnit);
?你是不是也想把inner join
放在sql语句中?
是的。它也给出了一个错误。问题是 sql 中没有参数,只有表值参数 (@tvpBusUnit):“select bus_unit_id, Business_Unit from tblBUSINESS_UNIT b join @tvpBusUnit s on s.value = b.BUS_UNIT_ID”
【参考方案1】:
从您发布的链接中,我认为您访问结构化变量的方式不正确。
s.CreateSQLQuery("EXEC some_sp @id = :id, @par1 = :par1")
.SetStructured("id", dt)
您的代码没有使用:id
部分,即:tvpBusUnit
。
另请注意,TableType
(在TypeName
中)可能必须事先在数据库上创建。请检查这是否是必需的。从您的代码:
TypeName = "dbo.[DLTableTypeInt]",
这里提供了一些关于传递表值参数的讨论,但 NHibernate 有一个更新,而无需创建如下类型:
Passing table valued parameters to NHibernate。但这可能需要一个拉取请求。您提到的另一篇文章中提供的答案允许您创建此类类型,每个 TableType
一个。
【讨论】:
@tvpBusUnit
的数据需要传递给 nhibernate 到 sql 查询(不是存储过程)。第一个使用直接 sql 的示例工作并传递 @tvpBusUnit
的数据。有没有办法修改 setStructured 代码来传递这个条件。
@Remy,是的,我的意思是用于 sql 查询。它适用于不使用 :X 格式的存储过程。对于原始 sql 查询,您将需要 :X 格式。抱歉延迟回复...希望这会有所帮助。我可以建议您在 sql 中创建一个表值参数,然后使用 :X 格式对其进行分配。我为传递的 XML 参数执行此操作:.SetParameter("Ids", sb.ToString(), NHibernateUtil.StringClob)
并将其设置在 SQL 中,如下所示:SET @IdsXml = :Ids;
@Remy,对于存储过程,输入参数从存储过程的定义中是明确的,但是对于原始的sql查询,没有提供输入值的标准方法。 NHibernate 似乎允许使用 :X 格式进行此操作。这是我的理解 - 没有在某处读过。
@Remy 或其他任何人,如果这个答案对你有用……你能把它标记为这样吗?这也将帮助其他人,也为我证实了这一点。谢谢!以上是关于SqlDbType.Structured 在 NHibernate 中传递表值参数以选择不带:param?的主要内容,如果未能解决你的问题,请参考以下文章