2016-01-05 61 views
3

我相信我發現瞭如何在Cassandra csharp驅動程序(2.7.3版)中的StatementFactory中緩存預準備語句的邏輯。這是用例。在Cassandra Csharp驅動程序中準備好的語句緩存問題

Guid key = Guid.NewGuid(); // your key 

ISession session_foo = new Session("foo"); //This is pseudo code 
ISession session_bar = new Session("bar"); 

var foo_mapper = new Mapper(session_foo); //table foo_bar 
var bar_mapper = new Mapper(session_bar); //table foo_bar 

await Task.WhenAll(
    foo_mapper.DeleteAsync<Foo>("WHERE id = ?", key), 
    bar_mapper.DeleteAsync<Bar>("WHERE id = ?", key)); 

我們發現運行後刪除後,只有第一個請求成功。在StatementFactory

public Task<Statement> GetStatementAsync(ISession session, Cql cql) 
    { 
     if (cql.QueryOptions.NoPrepare) 
     { 
      // Use a SimpleStatement if we're not supposed to prepare 
      Statement statement = new SimpleStatement(cql.Statement, cql.Arguments); 
      SetStatementProperties(statement, cql); 
      return TaskHelper.ToTask(statement); 
     } 
     return _statementCache 
      .GetOrAdd(cql.Statement, session.PrepareAsync) 
      .Continue(t => 
      { 
       if (_statementCache.Count > MaxPreparedStatementsThreshold) 
       { 
        Logger.Warning(String.Format("The prepared statement cache contains {0} queries. Use parameter markers for queries. You can configure this warning threshold using MappingConfiguration.SetMaxStatementPreparedThreshold() method.", _statementCache.Count)); 
       } 
       Statement boundStatement = t.Result.Bind(cql.Arguments); 
       SetStatementProperties(boundStatement, cql); 
       return boundStatement; 
      }); 
    } 

的源代碼跳水後,您可以看到緩存僅使用CQL語句。在我們的例子中,我們在不同的密鑰空間(又名會話)中有相同的表名。我們在兩個查詢中的cql語句看起來都是一樣的。即DELETE FROM foo_bar WHERE id =?

如果我不得不猜測,我會說一個簡單的解決辦法是將cql語句和keyspace結合在一起作爲緩存鍵。

有沒有其他人遇到過這個問題?

回答

4

作爲一種簡單的解決方法,我使用DoNotPrepare

await _mapper.DeleteAsync<Foo>(Cql.New("WHERE id = ?", key).WithOptions(opt => opt.DoNotPrepare())); 

跳過緩存我還發現了一個懸而未決的問題與Datastax

2

有一個open ticket to fix this behaviour

作爲一種變通方法,在創建Mapper時,可以使用不同的MappingConfiguration實例:

ISession session1 = cluster.Connect("ks1"); 
ISession session2 = cluster.Connect("ks2"); 

IMapper mapper1 = new Mapper(session1, new MappingConfiguration()); 
IMapper mapper2 = new Mapper(session2, new MappingConfiguration()); 

或者,您可以重用單個ISession實例,並完全符合你的查詢,包括密鑰空間。

MappingConfiguration.Global.Define(
    new Map<Foo>() 
     .TableName("foo") 
     .KeyspaceName("ks1"), 
    new Map<Bar>() 
     .TableName("bar") 
     .KeyspaceName("ks2")); 

ISession session = cluster.Connect(); 
IMapper mapper = new Mapper(session); 
相關問題