Параметризовать запрос DocumentDB с предложением IN

У меня есть запрос, похожий на следующий, который я пытаюсь параметризовать:

List<string> poiIDs = /*List of poi ids*/;
List<string> parameterNames = /*List of parameter names*/;

string inClause = string.Join(",", parameterNames);

string query = string.Format("SELECT c.id AS poiID, c.poiName, c.latitude, c.longitude FROM c WHERE c.clusterName = @clusterName AND c.id IN ({0}) AND c.deleted = false", inClause);

IQueryable<POI> queryResult = Client.CreateDocumentQuery<POI>(Collection.SelfLink, new SqlQuerySpec
            {
                QueryText = query,
                Parameters = new SqlParameterCollection()
                {
                    new SqlParameter("@clusterName", "POI"),
                    // How do I declare the dynamically generated parameters here
                    // as new SqlParameter()?
                }
             });

Как объявить динамически сгенерированные параметры как новый SqlParameter() для свойства Parameters SqlQuerySpec, чтобы создать запрос документа?


person Abhishek Das    schedule 30.10.2015    source источник
comment
stackoverflow.com/questions/337704/?   -  person Soner Gönül    schedule 30.10.2015
comment
Спасибо за ваш ответ, но я работаю с Azure DocumentDB, а не с SQLServer.   -  person Abhishek Das    schedule 30.10.2015


Ответы (4)


Вы можете создать динамический параметризованный запрос следующим образом:

// DocumentDB query 
 // POINT TO PONDER: create the formatted query, so that after creating the   dynamic query we'll replace it with dynamically created "SQL Parameter/s"
            var queryText = @"SELECT
                                us.id,
                                us.email,           
                                us.status,
                                us.role
                            FROM user us
                            WHERE us.status = @userStatus AND us.email IN ({0})";


            // contain's list of emails  
            IList<string> emailIds = new List<string>();
            emailIds.Add("[email protected]");
            emailIds.Add("[email protected]");

            #region Prepare the query

            // simple parameter: e.g. check the user status
            var userStatus = "active";
            var sqlParameterCollection = new SqlParameterCollection { new SqlParameter("@userStatus", userStatus) };                

            // IN clause: with list of parameters:
            // first: use a list (or array) of string, to keep  the names of parameter          
            // second: loop through the list of input parameters ()
            var namedParameters = new List<string>();
            var loopIndex = 0;

            foreach (var email in emailIds)
            {
                var paramName = "@namedParam_" + loopIndex;
                namedParameters.Add(paramName);

                var newSqlParamter = new SqlParameter(paramName, email);
                sqlParameterCollection.Add(newSqlParamter);

                loopIndex++;
            }

            // now format the query, pass the list of parameter into that
            if (namedParameters.Count > 0)
                queryText = string.Format(queryText, string.Join(" , ", namedParameters));

                // after this step your query is something like this  
                // SELECT
                //                 us.id,
                //                 us.email,            
                //                 us.status,
                //                 us.role
                //             FROM user us
                //             WHERE us.status = @userStatus AND us.email IN (@namedParam_0, @namedParam_1, @namedParam_2)

            #endregion //Prepare the query

            // now inject the parameter collection object & query
            var users = Client.CreateDocumentQuery<Users>(CollectionUri, new SqlQuerySpec
            {
                QueryText = queryText,
                Parameters = sqlParameterCollection
            }).ToList();
person Raushan Kuamr Jha    schedule 13.04.2016

Ниже приведен SQL-запрос, который затем можно запустить в коллекции DocumentDB, чтобы получить документы по их идентификаторам.

var query = $"SELECT * FROM p WHERE p.id IN ('{string.Join("', '", arrayOfIds)}')";
person Skorunka František    schedule 29.03.2017
comment
Просто добавьте объяснение в свой фрагмент и объясните, что вы делаете;) - person Alex Cio; 29.03.2017
comment
Торопился и просто держал ответ в буфере обмена ;). Готово. - person Skorunka František; 30.03.2017
comment
Без ненависти, я просто просмотрел некоторые ответы :) - person Alex Cio; 31.03.2017

SDK DocumentDB не поддерживает параметризованные запросы IN.

Судя по потоку SO в комментарии выше, SQL тоже этого не делает. Как упоминалось в другом потоке, вы можете использовать LINQ в качестве обходного пути.

person Andrew Liu    schedule 04.11.2015
comment
Вы можете параметризовать SQL-запрос с помощью предложения IN. См.: stackoverflow.com/questions/337704/ - person Abhishek Das; 05.11.2015
comment
Насколько я понимаю, использование LINQ вместо этого не помогает решить проблему с SQL-инъекцией. Имеет ли это? - person Abhishek Das; 05.11.2015
comment
Согласно потоку, на который вы ссылаетесь, SQL не поддерживает параметризованный IN как встроенную функцию. Ответы в ветке являются общими обходными путями и могут быть адаптированы и к DocumentDB. - person Andrew Liu; 05.11.2015
comment
Попробуйте адаптировать stackoverflow.com/a/337792/319795 или stackoverflow.com/a/380185/319795 - person Andrew Liu; 05.11.2015
comment
Количество параметров мне неизвестно, поскольку они заполняются во время выполнения в зависимости от пользовательского ввода. Поэтому я не могу объявить SQLParameters в SQLParameterCollection при создании моего запроса. Я хочу знать, можно ли настроить запрос так же, как в теме, которую я разместил в своем комментарии. Если да, пожалуйста, опубликуйте фрагмент кода. - person Abhishek Das; 05.11.2015

Почему бы не использовать метод ArrayContains? Вот пример в узле

sqlQuery = {
        query: 'SELECT * FROM t WHERE ARRAY_CONTAINS(@idList, t.id)',
        parameters: [
            {
                name: '@idList',
                value: ['id1','id2','id3'],
            },
        ],
    };
person Kevin Mansel    schedule 23.01.2020