如何更改我的方法只返回Cliente
类型的一个对象?
我的方法:
public IQueryable <Cliente> GetByEmailCpf(string email, string cpf, string colletionId)
{
FeedOptions queryOptions = new FeedOptions {
MaxItemCount = -1
};
IQueryable <Cliente> cliente = client.CreateDocumentQuery <Cliente> (
UriFactory.CreateDocumentCollectionUri(databaseId, colletionId), queryOptions)
.Where(x => x.Email == email || x.Cpf == cpf);
return cliente;
}
DocumentQueryException:查询表达式无效,表达式https://127.0.0.1:8081/dbs/Comosos/colls/Cliente.Where(x =>((x.Email == value(LR.Mobile.Data.Repositories.ModuloProduto.Classes.ClienteRepository + <> c__DisplayClass5_0).email)OrElse(x.Cpf == value(LR) .Mobile.Data.Repositories.ModuloProduto.Classes.ClienteRepository + <> c__DisplayClass5_0).cpf)))。不支持FirstOrDefault()。支持的表达式是'Queryable.Where','Queryable.Select'和'Queryable.SelectMany'
如您的错误所述,您似乎正在尝试使用FirstOrDefault。目前不支持此功能,根据Azure Cosmos反馈网站,目前不是优先事项:
Add support for single entity retrieval instead of IEnumarable
在该帖子中,Microsoft建议采用以下解决方法:
相反,我们建议您对Single()和First()使用Take(1).AsEnumerable()然后使用.First()或.Single()或.FirstOrDefault()。 Take(1)被翻译为SELECT TOP 1并在服务器端处理,因此比之前的建议更有效,并且是您正在尝试实现的目标。
通过包含Take(1)
语句,只有第一个结果将被加载到内存中而不是where子句的整个结果中。
在您的代码中,这将转换为以下内容:
var query = client.CreateDocumentQuery<Cliente>(
UriFactory.CreateDocumentCollectionUri(databaseId, colletionId), queryOptions)
.Where(x => x.Email == email || x.Cpf == cpf)
.Take(1)
.AsEnumerable()
.FirstOrDefault();
正如其他人所提到的,不要忘记将您的退货类型更新为Cliente
。
你必须做这样的事情:
public Cliente GetByEmailCpf(string email, string cpf, string colletionId) {
FeedOptions queryOptions = new FeedOptions {
MaxItemCount = -1
};
IQueryable <Cliente> cliente = client.CreateDocumentQuery <Cliente> (
UriFactory.CreateDocumentCollectionUri(databaseId, colletionId), queryOptions)
.Where(x => x.Email == email || x.Cpf == cpf).ToList().FirstOrDefault();
return cliente;
}
但是在较大的集合中,不建议这样做。建议您使用异步页面对结果进行分页。
public async Task<Cliente> GetByEmailCpf(string email, string cpf, string colletionId) {
FeedOptions queryOptions = new FeedOptions {
MaxItemCount = -1
};
var query = client.CreateDocumentQuery <Cliente> (
UriFactory.CreateDocumentCollectionUri(databaseId, colletionId), queryOptions)
.Where(x => x.Email == email || x.Cpf == cpf).AsDocumentQuery();
while (query.HasMoreResults)
{
var items = await query.ExecuteNextAsync<Cliente>();
if(items.Count > 0)
return items.FirstOrDefault();
}
return null;
}
如果您只想从集合中检索单个文档,则需要将方法返回类型更改为Cliente
而不是IQueryable <Cliente>
。
public Cliente GetByEmailCpf(string email, string cpf, string colletionId)
{
FeedOptions queryOptions = new FeedOptions
{
MaxItemCount = -1
};
var query = client.CreateDocumentQuery<Cliente>(
UriFactory.CreateDocumentCollectionUri(databaseId, colletionId), queryOptions)
.Where(x => x.Email == email || x.Cpf == cpf);
//If your collection have more than one document of specific email and cpf then
Cliente cliente = query.ToList().FirstOrDefault();
//If your collection have only single document of specific email and cpf then
Cliente cliente = query.ToList().SingleOrDefault();
return cliente;
}
尝试一次它可以帮助你。
我以前有这个扩展:
public static T TakeOne<T>(this IQueryable<T> source)
{
var documentQuery = source.AsDocumentQuery();
if (documentQuery.HasMoreResults)
{
var queryResult = documentQuery.ExecuteNextAsync<T>().Result;
if (queryResult.Any())
{
return queryResult.Single<T>();
}
}
return default(T);
}
然后你可以这样做:
Cliente cliente = client.CreateDocumentQuery <Cliente> (
UriFactory.CreateDocumentCollectionUri(databaseId, colletionId), queryOptions)
.Where(x => x.Email == email || x.Cpf == cpf).TakeOne();