none
A consulta "trazer todos" só retorna mil registros! Pq? RRS feed

  • 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
    segunda-feira, 10 de outubro de 2011 11:11

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
    segunda-feira, 21 de novembro de 2011 13:46

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
    segunda-feira, 10 de outubro de 2011 12:41
  • 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 ?

     

    segunda-feira, 21 de novembro de 2011 12:46
  • 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
    segunda-feira, 21 de novembro de 2011 13:46
  • 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
    segunda-feira, 21 de novembro de 2011 17:05