如何在Cassandra c#驱动程序中存储分页状态?

问题描述 投票:0回答:2

我已经阅读了几个使用Cassandra c#驱动程序实现手动分页的链接。

链接提到:

Backward paging in cassandra c# driver

https://datastax.github.io/csharp-driver/features/paging/

我的要求:

我试图得到所有不同的分区键表格列表,这个表格太大了。

由于大小,Cassandra db在检索它们或首次执行查询之间抛出错误。现在假设在获取100000个不同的分区键后它失败了,我将使用Cassandra c#driver提供的分页状态。

现在,我在未能记录文件之前保存最后一个可用的页面状态,并再次使用它以从失败的地方继续。

我使用以下命令将分页状态保存到日志文件中:

Encoding.ASCII.GetString(pagingState);

并使用以下方法检索表单日志文件:

Encoding.ASCII.GetBytes(pagingState);

但是当我将它传递给.SetPagingState(pagingState)并执行查询时,它会抛出异常,如:

java.lang.IllegalStateException:在前一个迭代器被完全消耗之前,不能调用hasNext()

我在保存到文件之前和从文件中检索它们之后比较逐字节数组字节。字节数组中的几个值不同。我尝试使用UIF8编码,但没有用。

注意:我在没有转换的情况下传递字节数组时效果很好。我的意思是下面的条件代码完美无缺。

if (pagingState != null)
{
     GenerateInitialLogs(pagingState);
}

全功能:

    private void BtnGetPrimaryKeys_Click(object sender, EventArgs e)
    {
        string fileContent = File.ReadAllText("D:/Logs/log.txt");            
        if(fileContent.Length > 0)
        {
            GenerateInitialLogs(Encoding.ASCII.GetBytes(fileContent));
        }
        else
        {
            GenerateInitialLogs(null);
        }
    }

    private void Log(byte[] pagingState)
    {
        File.WriteAllText("D:/Logs/log.txt", Encoding.ASCII.GetString(pagingState));    
    }

    private int GenerateInitialLogs(byte[] pagingState)
    {            
        try
        {
            RowSet rowSet = BLL.SelectDistinctPrimaryKeys(pagingState);

            List<PrimaryKey> distinctPrimaryKeys = new List<PrimaryKey>();
            foreach (Row row in rowSet)
            {
                if (rowSet.PagingState != null) { pagingState = new byte[rowSet.PagingState.Length]; }
                pagingState = rowSet.PagingState;
            }
            Log(pagingState)

            if (pagingState != null)
            {
                GenerateInitialLogs(pagingState);
            }
        }
        catch(Exception ex)
        {
            throw ex;
        }
    }

    public static RowSet SelectDistinctPrimaryKeysFromTagReadings(byte[] pagingState)
    {
        try
        {
            // will execute on continuing after failing in between. 
            if (pagingState != null)
            {
                PreparedStatement preparedStatement = BLL.currentSession.Prepare("SELECT DISTINCT \"Url\",\"Id\" FROM \"Readings\" ");
                BoundStatement boundStatement = preparedStatement.Bind();
                IStatement istatement = boundStatement.SetAutoPage(false).SetPageSize(1000).SetPagingState(pagingState);
                return BLL.currentSession.Execute(istatement);
            }
            else
            {
                PreparedStatement preparedStatement = BLL.currentSession.Prepare("SELECT DISTINCT \"Url\",\"Id\" FROM \"Readings\" ");
                BoundStatement boundStatement = preparedStatement.Bind();
                IStatement istatement = boundStatement.SetAutoPage(false).SetPageSize(1000);
                return BLL.currentSession.Execute(istatement);                    
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
c# datastax-enterprise cassandra-3.0
2个回答
2
投票

我没想到这个解决方案。这是由Jorge Bay Gondra(datastax的员工)完成的。

原始答案:

https://groups.google.com/a/lists.datastax.com/forum/#!topic/csharp-driver-user/4XWTXZC-hyI

解:

无法将它们转换为ASCII或UIF8或任何编码,因为它们不代表文本。

使用这些函数将字节数组转换为十六进制,反之亦然。

public static string ByteArrayToHexaDecimalString(byte[] bytes)
{
     StringBuilder stringBuilder = new StringBuilder(bytes.Length * 2);
     foreach (byte b in bytes) { stringBuilder.AppendFormat("{0:x2}", b); }
     return stringBuilder.ToString();
}

public static byte[] HexaDecimalStringToByteArray(String hexaDecimalString)
{
     int NumberChars = hexaDecimalString.Length;
     byte[] bytes = new byte[NumberChars / 2];
     for (int i = 0; i < NumberChars; i += 2)
     { 
         bytes[i / 2] = Convert.ToByte(hexaDecimalString.Substring(i, 2), 16); 
     }
     return bytes;
}

0
投票

我还发现Encoding.UTF8.GetString和GetBytes在所有情况下都不起作用,虽然对某些情况有效,但发现Convert.ToBase64String并且反向工作正常。

public static string ConvertPagingStateToString(byte[] pagingState) 
     => Convert.ToBase64String(pagingState);

public static byte[] ConvertStringToPagingState(string pagingStateString) 
     => Convert.FromBase64String(pagingStateString);
© www.soinside.com 2019 - 2024. All rights reserved.