Usuário com melhor resposta
A consulta "trazer todos" só retorna mil registros! Pq?

Pergunta
-
Estou inserindo registros nas table storages do azure usando o seguinte código:
public void Insert(TableServiceEntity Entity) { Database.DataContext.AddObject(Entity.GetType().Name, Entity); Database.DataContext.SaveChanges(); }
E para recuperar todos os registros desta tabela estou usando a seguinte função:
public T[] List() { var query = from c in Database.DataContext.CreateQuery<T>(this.TableName) select c; return query.ToArray(); }
Porém, está retornando apenas 1000 registros e nunca retorna todos os registros da tabela porém eu sei que os registros estão na tabela pois testei fazendo uma consulta específica com o "where" e consegui visualizar dados que inicialmente não apareceram nesta consulta.Gostaria de poder retornar todos os registros . Como devo fazer ?
- Editado Rick Sam segunda-feira, 10 de outubro de 2011 11:12
Respostas
-
Rick,
O Table Service apresenta várias situações em que poderá limitar a quantidade de registros retornados; por exemplo, por exceder o limite máximo de registros em uma operação; por atravessar a fronteira de particionamento; por excesso de retries.
Nestes casos a consulta retorna o chamado "continuation token" que pode ser utilizado para obter mais um conjunto de resultados. Note que é possível que uma consulta não retorne nenhum resultado, apenas o continuation token; neste caso este token deverá ser utilizado para o próximo estágio da consulta.
Tudo isso pode ficar bem complexo, mas há um jeito simples de acessar todos os dados de uma query: usar uma query do tipo CloudTableQuery e chamar o método Execute(). Você pode gerar um CloudTableQuery a partir de um objeto DataServiceQuery através do método AsTableServiceQuery.
O método Execute() do CloudTableQuery irá automaticamente continuar as consultas usando o continuation token até o final dos dados.
Por exemplo:
foreach (var entity in context.CreateQuery<ProductEntity>("Products").AsTableServiceQuery<ProductEntity>().Execute()) { Console.WriteLine("Product name: {0} Price: {1}", entity.ProductName, entity.Price); }
Note que o uso indiscriminado de consultas em um grande conjunto de dados no Table Service pode não atender aos requisitos de desempenho do aplicativo. É preciso entender as características deste serviço, afinal trata-se de armazenamento de dados distribuídos. Uma estratégia é utilizar as propriedades PartitionKey e RowKey de forma otimizada para acelerar as consultas.
Note também que se o que você deseja é paginação, terá que lidar especificamente com o continuation token; neste caso não é desejável chamar apenas o método Execute(), que irá buscar TODOS os registros da consulta.
Veja algumas páginas sobre o assunto:
- http://msdn.microsoft.com/en-us/library/windowsazure/ee741713.aspx
- http://msdn.microsoft.com/en-us/library/ee758410.aspx
- http://scottdensmore.typepad.com/blog/2010/04/paging-with-windows-azure-table-storage.html
- http://blogs.msdn.com/b/jimoneil/archive/2010/10/05/azure-home-part-7-asynchronous-table-storage-pagination.aspx
- http://convective.wordpress.com/2010/02/06/queries-in-azure-tables/
- http://dunnry.com/blog/2011/08/24/HandlingContinuationTokensInWindowsAzureGotcha.aspx
Fernando Correia
pensandoazure.wordpress.com
@facorreia- Sugerido como Resposta Fernando Correia segunda-feira, 21 de novembro de 2011 13:46
- Marcado como Resposta Rick Sam terça-feira, 22 de novembro de 2011 11:33
Todas as Respostas
-
Rick, Isso é uma caracteristica do Azure pára consultas sem filtro; http://convective.wordpress.com/2010/02/06/queries-in-azure-tables/
Procure pelo uso de Take e Skip com Entity Framework para páginação de dados
http://msdn.microsoft.com/en-us/data/gg190738
Olavo Oliveira Neto
http://olavooneto.wordpress.com
Twitter @Olavooneto
Se for útil marque como resposta e faça um Developer feliz :)- Sugerido como Resposta Francisco Gonçalves segunda-feira, 17 de outubro de 2011 21:38
- Não Sugerido como Resposta Rick Sam segunda-feira, 21 de novembro de 2011 13:10
-
Tentei usar o Take e Skip para acessar os dados da tabela mas o comando Skip não funciona o take funciona!
Se eu fizer assim, funciona :
return query.Take(1000).ToArray();
mas o comando acima só me traz os 1000 primeiros registros e eu gostaria de obter os registros acima de 1000 nesta partition então tentei fazer o seguinte:
return query.Skip(1000).Take(1000).ToArray();
Mas ai dá erro ! como posso acessar os dados que estão nesta partition ?
-
Rick,
O Table Service apresenta várias situações em que poderá limitar a quantidade de registros retornados; por exemplo, por exceder o limite máximo de registros em uma operação; por atravessar a fronteira de particionamento; por excesso de retries.
Nestes casos a consulta retorna o chamado "continuation token" que pode ser utilizado para obter mais um conjunto de resultados. Note que é possível que uma consulta não retorne nenhum resultado, apenas o continuation token; neste caso este token deverá ser utilizado para o próximo estágio da consulta.
Tudo isso pode ficar bem complexo, mas há um jeito simples de acessar todos os dados de uma query: usar uma query do tipo CloudTableQuery e chamar o método Execute(). Você pode gerar um CloudTableQuery a partir de um objeto DataServiceQuery através do método AsTableServiceQuery.
O método Execute() do CloudTableQuery irá automaticamente continuar as consultas usando o continuation token até o final dos dados.
Por exemplo:
foreach (var entity in context.CreateQuery<ProductEntity>("Products").AsTableServiceQuery<ProductEntity>().Execute()) { Console.WriteLine("Product name: {0} Price: {1}", entity.ProductName, entity.Price); }
Note que o uso indiscriminado de consultas em um grande conjunto de dados no Table Service pode não atender aos requisitos de desempenho do aplicativo. É preciso entender as características deste serviço, afinal trata-se de armazenamento de dados distribuídos. Uma estratégia é utilizar as propriedades PartitionKey e RowKey de forma otimizada para acelerar as consultas.
Note também que se o que você deseja é paginação, terá que lidar especificamente com o continuation token; neste caso não é desejável chamar apenas o método Execute(), que irá buscar TODOS os registros da consulta.
Veja algumas páginas sobre o assunto:
- http://msdn.microsoft.com/en-us/library/windowsazure/ee741713.aspx
- http://msdn.microsoft.com/en-us/library/ee758410.aspx
- http://scottdensmore.typepad.com/blog/2010/04/paging-with-windows-azure-table-storage.html
- http://blogs.msdn.com/b/jimoneil/archive/2010/10/05/azure-home-part-7-asynchronous-table-storage-pagination.aspx
- http://convective.wordpress.com/2010/02/06/queries-in-azure-tables/
- http://dunnry.com/blog/2011/08/24/HandlingContinuationTokensInWindowsAzureGotcha.aspx
Fernando Correia
pensandoazure.wordpress.com
@facorreia- Sugerido como Resposta Fernando Correia segunda-feira, 21 de novembro de 2011 13:46
- Marcado como Resposta Rick Sam terça-feira, 22 de novembro de 2011 11:33
-
Consegui retornar os resultados que precisava conforme a explicação acima. Veja como ficou meu código:
var query = from c in Database.DataContext.CreateQuery<T>(this.TableName) where c.Year == Year.ToString("0000") select c; CloudTableQuery<T> c_query = query.AsTableServiceQuery<T>(); return c_query.Execute().ToArray();
O Mesmo consegui para consultas com take permitindo a paginação dos dados, exemplo:var query = from c in Database.DataContext.CreateQuery<T>(this.TableName) where c.Year == Year.ToString("0000") select c; CloudTableQuery<T> c_query = query.Take(100).AsTableServiceQuery<T>(); IAsyncResult IAResult = c_query.BeginExecuteSegmented(null, query); ResultSegment<T> ResultSeg = c_query.EndExecuteSegmented(IAResult); List<T> lst = new List<T>(); while (ResultSeg.ContinuationToken != null) { lst.AddRange(c_query.Execute(ResultSeg.ContinuationToken)); ResultSeg = ResultSeg.GetNext(); } return lst.ToArray();
Valeu pela ajuda Fernando!- Editado Rick Sam terça-feira, 22 de novembro de 2011 11:33