Используя клиентский SDK C # .Net, я вызываю метод ExecuteStoredProcedureAsync следующим образом:

sproc_response = await client.ExecuteStoredProcedureAsync<Document>(sproc_uri, new RequestOptions { PartitionKey = new PartitionKey( my_partition_key) }, doc_to_create );

Код хранимой процедуры выглядит следующим образом:

     sproc.Body = @"function( doc ) {

            var collection = getContext().getCollection();    

            var response = getContext().getResponse();    

            function create_doc_callback( err, doc_created, options ) {

               if(err) throw new Error('Error creating document: ' + err.message);                              

               response.setBody( doc_created );

            }

            collection.createDocument( collection.getSelfLink(), doc, {}, create_doc_callback );

        }";

Это ВСЕГДА приводит к возникновению следующего исключения:

Ошибка при создании документа: запросы, исходящие из сценариев, не могут ссылаться на ключи раздела, кроме того, для которого был отправлен запрос клиента.

Есть ли какая-либо документация или пример, который ясно показывает, как вызвать хранимую процедуру с использованием ключа раздела - очевидно, мне что-то не хватает!

5
bdcoder 29 Июн 2017 в 19:42
Какое значение установлено для ключа раздела в doc_to_create. Возможно ли, что оно отличается от значения, которое вы передаете для ключа раздела в параметрах запроса?
 – 
Jesse Carter
29 Июн 2017 в 20:39
Doc_to_create является POCO (обычный старый объект CLR) и не имеет свойства ключа раздела ... Требуется ли для метода collection.createDocument () объект Microsoft.Azure.Documents.Document? Понятия не имею, так как не могу найти ДОКУМЕНТАЦИЮ!
 – 
bdcoder
29 Июн 2017 в 21:02
Когда вы используете POCO, он сериализуется и передается в Cosmos. У объекта должно быть свойство, которое соответствует тому, что вы выбрали для своего ключа раздела, и именно поэтому он знает, где разместить объект. Если вы не укажете его, он попадет в специальный раздел, который по сути не определен.
 – 
Jesse Carter
29 Июн 2017 в 21:06

1 ответ

Лучший ответ

Когда вы создаете секционированную коллекцию в Cosmos, вам необходимо выбрать ключ секции, который является путем в представлении JSON ваших документов, который будет использоваться для размещения документа в правильном разделе. Если вы пытаетесь вставить документ без ключа раздела, он будет сгруппирован в специальный раздел для документов без ключа раздела. Вы указываете, что хранимая процедура должна выполняться в контексте данного раздела, но затем пытаетесь использовать ее для вставки документа в другой раздел (неопределенный). Убедитесь, что на вашем POCO есть свойство, которое соответствует значению, которое вы выбрали для ключа раздела в вашей коллекции.

Вы четко знаете, в какой раздел вы хотите поместить документ, поскольку вы передаете значение в RequestOptions для PartitionKey. Теперь убедитесь, что ваш POCO включает это значение в свойство, которое соответствует ключу раздела, который вы выбрали при создании своей коллекции. У документа по-прежнему будет автоматически сгенерированный идентификатор, если вы его не предоставите. В качестве альтернативы вы можете просто добавить ключ раздела в свой документ внутри Sproc, когда вы имеете дело с динамическим JS-объектом.

doc.partitionKey = my_partition_key
7
Jesse Carter 30 Июн 2017 в 00:54
Привет, Джесси, спасибо, что нашли время объяснить. Когда я сохраняю объект POCO в DocumentDB, id use: response = await client.CreateDocumentAsync (col_uri, poco_obj); Что отлично работает и возвращает объект DocumentDB Document как таковой. Если моим ключом раздела является идентификатор документа, который создается автоматически, я ожидал, что вызов collection.createDocument () (в javascript) будет вести себя так же, но, похоже, это не так.
 – 
bdcoder
29 Июн 2017 в 23:33
Sproc может работать только с документами, которые имеют то же значение ключа раздела, что и тот, который указан в параметрах запроса для выполнения вызова sproc. По умолчанию, если вы создаете документ и не предоставляете идентификатор, идентификатор будет автоматически сгенерирован (случайным образом). Если ключом раздела является идентификатор документа, автоматически сгенерированный идентификатор не будет соответствовать идентификатору в параметрах запроса. Вот почему ошибка. Будет ли приемлемо для вашего сценария, что создаваемый документ будет иметь идентификатор, такой же, как значение PK из RequestOptions? Вы можете установить в JS: передать как 2-й параметр (pk) и установить: doc.id = pk.
 – 
Michael Koltachev
29 Июн 2017 в 23:57
1
Нет, это не так. Id и PartitionKey - разные вещи. Если вы не укажете идентификатор, он будет автоматически сгенерирован для вас. Если вы не укажете ключ раздела, документ будет помещен в раздел для неопределенных ключей раздела. Sproc не может работать с документами за пределами своего раздела. Вы ДОЛЖНЫ определить ключ раздела в документе, который соответствует тому, который вы передаете в Sproc.
 – 
Jesse Carter
30 Июн 2017 в 00:51
1
У меня была такая же проблема, и этот ответ прибил ее. К сожалению, я немного погнался за хвостом, потому что мое свойство POCO имело другой регистр, чем ключ раздела.
 – 
Prethen
16 Янв 2019 в 00:37
1
Вам необходимо указать значение ключа раздела. Не его название. Вызов его с "id" недействителен. Укажите фактический идентификатор документа.
 – 
Jesse Carter
30 Июл 2019 в 18:06