Documentdb 无法反序列化存储过程响应或将其转换为我定义的类型
Documentdb Failed to deserialize stored procedure response or convert it to my defined type
我的存储过程:(我通过 Azure Script Explorer 创建它)
function GetAllResources() {
var collection = getContext().getCollection();
// Query documents and take 1st item.
var isAccepted = collection.queryDocuments(
collection.getSelfLink(),
'SELECT * FROM MultiLanguage as m',
function (err, docs, options) {
if (err) throw err;
// Check the feed and if empty, set the body to 'no docs found',
// else take 1st element from feed
if (!docs || !docs.length) getContext().getResponse().setBody('no docs found');
else getContext().getResponse().setBody(JSON.stringify(docs));
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
}
存储过程可以从脚本资源管理器成功执行。
我调用存储过程的 C# 代码:
public async Task<IHttpActionResult> GetReources() {
client = new DocumentClient(new Uri(ConfigurationManager.AppSettings["endpoint"]), ConfigurationManager.AppSettings["authKey"]);
var collectionLink = UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId);
//var docs = await client.ReadDocumentFeedAsync(collectionLink, new FeedOptions { MaxItemCount = 10 });
//var docs = from d in client.CreateDocumentQuery<Models.Resource>(collectionLink)
// select d;
StoredProcedure storedProcedure = client.CreateStoredProcedureQuery(collectionLink).Where(c => c.Id == "GetAllResources").AsEnumerable().FirstOrDefault();
Models.Resource docs = await client.ExecuteStoredProcedureAsync<Models.Resource>(storedProcedure.SelfLink);
foreach (var d in docs) {
Models.Resource a = new Models.Resource();
a = docs;
//a.id = d.id;
//a.Scenario = d.Scenario;
//a.Translations = d.Translations;
//a.LastModified = d.LastModified;
//a.ModifiedBy = d.ModifiedBy;
//a.LastAccessed = d.LastAccessed;
resources.Add(a);
}
return Ok(resources);
}
首先,像
这样的 "foreach..." 有一个错误
foreach cannot operate on variables of type Models.Resource because it
doesn't contain a public definition of GetEnumerator.
然后我尝试将我的存储过程修改为只有 return 1 个结果并删除 foreach 行,然后我得到错误说
Failed to deserialize stored procedure response or convert it to type
'Models.Resource'
我只想return存储过程的结果作为我定义的class(Models.Resource)。如何做到这一点?
使用 CreateStoredProcedureUri 按名称获取存储过程会更简单,如下所示:
const string endpoint = "https://your.service.azure.com:443/";
const string authKey = "<your magic secret master key>==";
var client = new DocumentClient(new Uri(endpoint), authKey);
Uri sprocUri = UriFactory.CreateStoredProcedureUri("databaseName", "collectionName", "GetAllResources");
var result = await client.ExecuteStoredProcedureAsync<string>(sprocUri);
上面的存储过程将查询的结果(docs数组)序列化为字符串,如果你保持这种方式,sproc的结果将是字符串,我猜你需要手动反序列化为对象。您可以更简单地执行此操作,只需 return 来自 sproc 的文档并将结果作为对象(如 Models.Resource[]),序列化将自动发生。
如果将 sproc 更改为 return 只有一个文档(例如 __.response.setBody(docs[0]
)并且 Models.Resource 代表一项,那么调用是正确的:
Models.Resource doc = await client.ExecuteStoredProcedureAsync<Models.Resource>(sprocUri);
此外,要 // 查询文档并获取第一项,我不建议使用脚本,因为脚本有 运行ning JavsScript 引擎的开销。当您进行批量操作(以优化网络流量)或具有对服务器上的 运行 有意义的业务逻辑时,脚本就会启动。要获取第一项,您可以像这样从客户端查询:SELECT TOP 1 * FROM c.通常,您会在其中添加 WHERE 和 ORDER BY 子句。
github 上有许多 docdb 示例,例如 https://github.com/Azure/azure-documentdb-dotnet/tree/master/samples/code-samples/ServerSideScripts and https://github.com/Azure/azure-documentdb-dotnet/tree/master/samples/code-samples/Queries。
谢谢,
迈克尔
好的,让我们确保我们在同一页面上。
我正在使用与上面相同的存储过程。
我正在使用这样的客户端代码:
class Models
{
// This would have more properties, I am just using id which all docs would have.
public class Resource
{
[JsonProperty("id")]
public string Id { get; set; }
}
}
public async Task<IHttpActionResult> GetResources()
{
const string endpoint = "https://myservice.azure.com:443/";
const string authKey = "my secret key==";
var client = new DocumentClient(new Uri(endpoint), authKey);
Uri sprocUri = UriFactory.CreateStoredProcedureUri("db", "c1", "GetAllResources");
var serializedDocs = await client.ExecuteStoredProcedureAsync<string>(sprocUri);
Models.Resource[] resources = JsonConvert.DeserializeObject<Models.Resource[]>(serializedDocs);
return Ok(resources);
}
它工作正常。这是你在做的吗?
我的存储过程:(我通过 Azure Script Explorer 创建它)
function GetAllResources() {
var collection = getContext().getCollection();
// Query documents and take 1st item.
var isAccepted = collection.queryDocuments(
collection.getSelfLink(),
'SELECT * FROM MultiLanguage as m',
function (err, docs, options) {
if (err) throw err;
// Check the feed and if empty, set the body to 'no docs found',
// else take 1st element from feed
if (!docs || !docs.length) getContext().getResponse().setBody('no docs found');
else getContext().getResponse().setBody(JSON.stringify(docs));
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
}
存储过程可以从脚本资源管理器成功执行。
我调用存储过程的 C# 代码:
public async Task<IHttpActionResult> GetReources() {
client = new DocumentClient(new Uri(ConfigurationManager.AppSettings["endpoint"]), ConfigurationManager.AppSettings["authKey"]);
var collectionLink = UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId);
//var docs = await client.ReadDocumentFeedAsync(collectionLink, new FeedOptions { MaxItemCount = 10 });
//var docs = from d in client.CreateDocumentQuery<Models.Resource>(collectionLink)
// select d;
StoredProcedure storedProcedure = client.CreateStoredProcedureQuery(collectionLink).Where(c => c.Id == "GetAllResources").AsEnumerable().FirstOrDefault();
Models.Resource docs = await client.ExecuteStoredProcedureAsync<Models.Resource>(storedProcedure.SelfLink);
foreach (var d in docs) {
Models.Resource a = new Models.Resource();
a = docs;
//a.id = d.id;
//a.Scenario = d.Scenario;
//a.Translations = d.Translations;
//a.LastModified = d.LastModified;
//a.ModifiedBy = d.ModifiedBy;
//a.LastAccessed = d.LastAccessed;
resources.Add(a);
}
return Ok(resources);
}
首先,像
这样的 "foreach..." 有一个错误foreach cannot operate on variables of type Models.Resource because it doesn't contain a public definition of GetEnumerator.
然后我尝试将我的存储过程修改为只有 return 1 个结果并删除 foreach 行,然后我得到错误说
Failed to deserialize stored procedure response or convert it to type 'Models.Resource'
我只想return存储过程的结果作为我定义的class(Models.Resource)。如何做到这一点?
使用 CreateStoredProcedureUri 按名称获取存储过程会更简单,如下所示:
const string endpoint = "https://your.service.azure.com:443/";
const string authKey = "<your magic secret master key>==";
var client = new DocumentClient(new Uri(endpoint), authKey);
Uri sprocUri = UriFactory.CreateStoredProcedureUri("databaseName", "collectionName", "GetAllResources");
var result = await client.ExecuteStoredProcedureAsync<string>(sprocUri);
上面的存储过程将查询的结果(docs数组)序列化为字符串,如果你保持这种方式,sproc的结果将是字符串,我猜你需要手动反序列化为对象。您可以更简单地执行此操作,只需 return 来自 sproc 的文档并将结果作为对象(如 Models.Resource[]),序列化将自动发生。
如果将 sproc 更改为 return 只有一个文档(例如 __.response.setBody(docs[0]
)并且 Models.Resource 代表一项,那么调用是正确的:
Models.Resource doc = await client.ExecuteStoredProcedureAsync<Models.Resource>(sprocUri);
此外,要 // 查询文档并获取第一项,我不建议使用脚本,因为脚本有 运行ning JavsScript 引擎的开销。当您进行批量操作(以优化网络流量)或具有对服务器上的 运行 有意义的业务逻辑时,脚本就会启动。要获取第一项,您可以像这样从客户端查询:SELECT TOP 1 * FROM c.通常,您会在其中添加 WHERE 和 ORDER BY 子句。
github 上有许多 docdb 示例,例如 https://github.com/Azure/azure-documentdb-dotnet/tree/master/samples/code-samples/ServerSideScripts and https://github.com/Azure/azure-documentdb-dotnet/tree/master/samples/code-samples/Queries。
谢谢,
迈克尔
好的,让我们确保我们在同一页面上。
我正在使用与上面相同的存储过程。 我正在使用这样的客户端代码:
class Models
{
// This would have more properties, I am just using id which all docs would have.
public class Resource
{
[JsonProperty("id")]
public string Id { get; set; }
}
}
public async Task<IHttpActionResult> GetResources()
{
const string endpoint = "https://myservice.azure.com:443/";
const string authKey = "my secret key==";
var client = new DocumentClient(new Uri(endpoint), authKey);
Uri sprocUri = UriFactory.CreateStoredProcedureUri("db", "c1", "GetAllResources");
var serializedDocs = await client.ExecuteStoredProcedureAsync<string>(sprocUri);
Models.Resource[] resources = JsonConvert.DeserializeObject<Models.Resource[]>(serializedDocs);
return Ok(resources);
}
它工作正常。这是你在做的吗?