I have been trying to use the Devart Postgres EFCore library as this is used at the company I work at. The NpgSql lib works fine with Mass Transit from what I can tell.
However I almost immediately ran into a problem with Mass Transit and Devart.
Devart.Data.PostgreSql.PgSqlException (0x80004005): column "p0" does not exist
I tracked this down to the PostgresLockStatementFormatter
.AppendColumn
method.
Masstransit uses this to help build a sql statement which is executed as RawSql by the DbContext
. This is basically the statement:
var queryable = dbContext.Set<MyEntity>().FromSqlRaw(" SELECT * FROM \"my_entity\" WHERE \"correlation_id\" = :p0 FOR UPDATE", Guid.NewGuid());
It seems that the Devart libs don't like the use of parameters named @p0
The correct format for Devart is :p0
My approach was to replace the LockStatmentFormatter
method with my own implementation specific to Devart:
public class DevArtPostgresLockStatementFormatter : ILockStatementFormatter
{
public void Create(StringBuilder sb, string schema, string table)
{
sb.AppendFormat("SELECT * FROM {0} WHERE ", FormatTableName(schema, table));
}
public void AppendColumn(StringBuilder sb, int index, string columnName)
{
if (index == 0)
sb.AppendFormat("\"{0}\" = :p0", columnName);
else
sb.AppendFormat(" AND \"{0}\" = :p{1}", columnName, index);
}
public void Complete(StringBuilder sb)
{
sb.Append(" FOR UPDATE");
}
public void CreateOutboxStatement(StringBuilder sb, string schema, string table, string columnName)
{
sb.AppendFormat(@"SELECT * FROM {0} ORDER BY ""{1}"" LIMIT 1 FOR UPDATE SKIP LOCKED", FormatTableName(schema, table), columnName);
}
static string FormatTableName(string schema, string table)
{
return string.IsNullOrEmpty(schema) ? $"\"{table}\"" : $"\"{schema}\".\"{table}\"";
}
}
This has to be placed in the service config section:
x.AddSagaRepository<MyStateMachine>()
.EntityFrameworkRepository(r =>
{
r.LockStatementProvider = new DevArtPostgresLockStatementProvider();
r.ExistingDbContext<MyDbContext>();
});
So this seems to fix my issue. I wonder is there anything else I should be aware of where it's also used.
This was my only real find in the durable Outbox feature I think?
I can test this but thought it was worth asking the question incase anyone has similar issues. Or perhaps it can help someone.
Thanks