我希望将一个I集合传递给一个将使用NHibernate映射的存储过程。这项技术是在Sql Server2008中引入的(更多信息请点击这里=> Table-Valued Parameters )。我只是不想在一个nvarchar
参数中传递多个ids,然后在SQL Server端砍掉它的值。
发布于 2010-09-28 03:08:32
我的第一个特别想法是实现我自己的IType
。
public class Sql2008Structured : IType {
private static readonly SqlType[] x = new[] { new SqlType(DbType.Object) };
public SqlType[] SqlTypes(NHibernate.Engine.IMapping mapping) {
return x;
}
public bool IsCollectionType {
get { return true; }
}
public int GetColumnSpan(NHibernate.Engine.IMapping mapping) {
return 1;
}
public void NullSafeSet(DbCommand st, object value, int index, NHibernate.Engine.ISessionImplementor session) {
var s = st as SqlCommand;
if (s != null) {
s.Parameters[index].SqlDbType = SqlDbType.Structured;
s.Parameters[index].TypeName = "IntTable";
s.Parameters[index].Value = value;
}
else {
throw new NotImplementedException();
}
}
#region IType Members...
#region ICacheAssembler Members...
}
不再实现更多的方法;所有其他方法中都有一个throw new NotImplementedException();
。接下来,我为IQuery
创建了一个简单的扩展。
public static class StructuredExtensions {
private static readonly Sql2008Structured structured = new Sql2008Structured();
public static IQuery SetStructured(this IQuery query, string name, DataTable dt) {
return query.SetParameter(name, dt, structured);
}
}
我的典型用法是
DataTable dt = ...;
ISession s = ...;
var l = s.CreateSQLQuery("EXEC some_sp @id = :id, @par1 = :par1")
.SetStructured("id", dt)
.SetParameter("par1", ...)
.SetResultTransformer(Transformers.AliasToBean<SomeEntity>())
.List<SomeEntity>();
好吧,但是什么是"IntTable"
呢?它是为传递表值参数而创建的SQL类型的名称。
CREATE TYPE IntTable AS TABLE
(
ID INT
);
而some_sp
可能是这样的
CREATE PROCEDURE some_sp
@id IntTable READONLY,
@par1 ...
AS
BEGIN
...
END
当然,它只适用于Sql Server2008,并且在这个特定的实现中使用单列DataTable
。
var dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
它只是POC,不是一个完整的解决方案,但它可以工作,并且在定制时可能会很有用。如果有人知道更好/更短的解决方案,请让我们知道。
发布于 2010-09-13 23:52:53
您可以轻松地传递多个值的集合。
示例:
var ids = new[] {1, 2, 3};
var query = session.CreateQuery("from Foo where id in (:ids)");
query.SetParameterList("ids", ids);
NHibernate将为每个元素创建一个参数。
发布于 2015-12-22 14:34:41
比公认的答案更简单的解决方案是使用ADO.NET,NHibernate允许用户将IDbCommands
登记到NHibernate事务中。
DataTable myIntsDataTable = new DataTable();
myIntsDataTable.Columns.Add("ID", typeof(int));
// ... Add rows to DataTable
ISession session = sessionFactory.GetSession();
using(ITransaction transaction = session.BeginTransaction())
{
IDbCommand command = new SqlCommand("StoredProcedureName");
command.Connection = session.Connection;
command.CommandType = CommandType.StoredProcedure;
var parameter = new SqlParameter();
parameter.ParameterName = "IntTable";
parameter.SqlDbType = SqlDbType.Structured;
parameter.Value = myIntsDataTable;
command.Parameters.Add(parameter);
session.Transaction.Enlist(command);
command.ExecuteNonQuery();
}
https://stackoverflow.com/questions/3701364
复制相似问题