2017-02-14 3 views
2

Я хочу передать коллекцию идентификаторов (через параметр table-valued) в NHibernate Оператор, который будет использоваться в соединении: В собственном SQL я могу это сделать (SQLSelectData ниже). Обратите внимание, что не находится в SqlCommand SQL нет :param:SqlDbType.Structured для передачи табличных значений в NHibernate для выбора без параметра: 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? Я пробовал принятое решение this question с использованием классов Sql2008Structured и Structured2008Extensions.

См ниже код, который вызывает 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 не существует в качестве имени параметра [выберите bus_unit_id, Business_Unit from tblBUSINESS_UNIT b join @tvpBusUnit s on s.value = b.BUS_UNIT_ID]

Как я могу это исправить?

+0

Что вы пытаетесь сделать? Я не уверен, что вы подразумеваете под «нет: param в sqlcommand sql». –

+0

Посмотрите на сообщение об ошибке, выделенное полужирным шрифтом. – Remy

+0

Вы пытались поставить '@' в 'sqlQuery.SetStructured (" tvpBusUnit ", tblBusUnit);'? Вы также хотели поставить 'inner join' в инструкции sql? –

ответ

0

Из ссылки, которую вы опубликовали, я думаю, что способ, которым вы обращаетесь к структурированной переменной, неверен.

s.CreateSQLQuery("EXEC some_sp @id = :id, @par1 = :par1") 
.SetStructured("id", dt) 

Ваш код не использует :id часть, то есть :tvpBusUnit.

Также обратите внимание, что на БД может быть необходимо создать TableTypeTypeName). Проверьте, требуется ли это. Из кода:

TypeName = "dbo.[DLTableTypeInt]", 

Некоторые обсуждение параметров таблицы значений проходных представлено здесь, но NHibernate имеет обновленную версию без создания типов, как это: Passing table valued parameters to NHibernate. Но для этого может потребоваться запрос на pull. Ответ, указанный в другом опубликованном вами сообщении, позволяет создавать такие типы, по одному для каждого TableType.

+0

Данные для '@ tvpBusUnit' должны быть передаваться в nhibernate в sql-запрос (НЕ хранимая процедура). Первый пример, который использует прямой sql, работает и передает данные для '@ tvpBusUnit'. Есть ли способ для mofidy setStructured code пройти для этого условия. – Remy

+0

@Remy, Да, я имел в виду это для sql-запроса. Для хранимых процедур вы не используете формат **: X **. Для raw sql-запроса вам понадобится формат **: X **. Извините за отложенный ответ ... Надеюсь, это поможет. Я могу посоветовать вам создать параметр значения таблицы внутри sql, а затем назначить его, используя формат: X. Я сделал это для параметра XML, который я передал как: '.SetParameter (« Идентификаторы », sb.ToString(), NHibernateUtil.StringClob) 'и установить его в SQL следующим образом:' SET @IdsXml =: Ids; ' –

+0

@Remy, для хранимых процедур входные параметры ясны из определения хранимой процедуры, но для сырых запросов sql есть нет стандартного способа предоставления входных значений. Кажется, что NHibernate позволяет это использовать формат: X. Это мое понимание - не читал это где-то. –

Смежные вопросы