如何更改我的方法以仅返回类型为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 ==值(LR.Mobile.Data.Repositories.ModuloProduto.Classes.ClienteRepository + <> c__DisplayClass5_0)。电子邮件) OrElse(x.Cpf == value(LR.Mobile.Data.Repositories.ModuloProduto.Classes.ClienteRepository + <> c__DisplayClass5_0).cpf)))。FirstOrDefault() 不被支持。支持的表达式为“ Queryable.Where”, “ Queryable.Select”和“ Queryable.SelectMany”
答案 0 :(得分:2)
如您的错误所述,您似乎正在尝试使用FirstOrDefault。目前尚不支持此功能,并且根据Azure Cosmos反馈网站,当前还没有将其优先考虑:
Add support for single entity retrieval instead of IEnumarable
在该帖子中,Microsoft建议采用以下解决方法:
相反,我们建议您使用Take(1).AsEnumerable(),然后对Single()和First()使用.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
。
答案 1 :(得分:1)
您将必须执行以下操作:
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;
}
答案 2 :(得分:0)
如果只想从集合中检索单个文档,则需要将方法返回类型更改为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;
}
尝试一次,可能对您有帮助。
答案 3 :(得分:0)
我以前有这个扩展名:
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();