2016-01-05 35 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); 
相关问题