我相信我发现了如何在Cassandra csharp驱动程序(版本2.7.3)的StatementFactory中缓存预准备语句的逻辑错误。这是用例。
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语句看起来都一样。即删除来自foo_bar WHERE id =?。
如果我不得不猜测,我会说一个简单的解决方法是将cql语句和键空间组合在一起作为缓存键。
之前是否有其他人遇到此问题?
答案 0 :(得分:4)
答案 1 :(得分:2)
有open ticket to fix this behaviour。
作为一种变通方法,您可以在创建MappingConfiguration
时使用其他Mapper
个实例:
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);