2017-11-11 81 views
0

我读过几个链接来实现使用Cassandra c#驱动程序进行手动分页。如何在Cassandra c#驱动中存储分页状态?

链接简称:

Backward paging in cassandra c# driver

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

我的要求:

我试图让所有不同分区键的列表形式表,其尺寸过大。

由于大小Cassandra db在检索它们或执行第一次查询时发生错误。现在假设在获取100000个不同的分区键后失败,我将使用Cassandra c#驱动程序提供的分页状态。

现在我正在保存最后一个可用的页面状态,然后再无法记录文件并再次使用它从失败的地方继续。

Encoding.ASCII.GetString(pagingState); 

而且使用检索格式的日志文件:

Encoding.ASCII.GetBytes(pagingState); 

但是,当我将它传递给.SetPagingState(pagingState)

我使用节省了寻呼状态到日志文件执行查询会抛出异常:

java.lang.IllegalState例外情况:无法调用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; 
     } 
    } 
+0

对我来说,将分页状态存储在日志文件中似乎不是个好主意。你真的必须把它存储在内存以外的任何地方吗?我也不觉得你的代码示例添加了任何东西,因为它是从日志文件中存储/获取的东西,可以解决这些问题。你可以包含完整的代码示例吗? –

+0

@SimonFontanaOscarsson你为什么认为它会弄乱的东西。每次形式文件时,我都没有阅读分页状态。我正在用最新的分页状态更新它。这里我的页面大小是1000,现在每获取1000条记录,它将更新日志。它只会在关闭中间应用程序并再次重新启动时从日志文件读取分页状态。我正在使用Windows应用程序。我添加了2个函数一个日志,其他的是按钮点击事件。 –

+0

@SimonFontanaOscarsson哦..还有一件事我忘了提。这是它会工作,当我传递字节数组,因为它是。我的意思是,如果 (pagingState!= null) { GenerateInitialLogs(pagingState); } 工作正常。只有转换有问题。我会更新有关的详细信息。 –

回答

1

该解决方案是不是我想通了。它由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; 
}