1

By session i mean Postgres session (same TCP connection).

My question related to https://stackoverflow.com/a/19410907/1251169 I need to pass user id to Postgres trigger. From my research i can only see a way in using set session custom.userid = 'NAME' (look at url above)

But it works only if i pass the query in the same session obviously. For example, this works

using (var context = new MyDbContext())
{
    context.Database.ExecuteSqlCommand("set session custom.userid  = 'NAME'; 
    insert into my_table values ('abc', 1)");
}

Inside the my_table trigger i can read

select current_setting('custom.userid'); // NAME

This doesn't work:

using (var context = new MyDbContext())
{
    context.Database.ExecuteSqlCommand("set session custom.userid  = 'NAME';");
    context.Database.ExecuteSqlCommand("insert into my_table values ('abc', 1)");
}

Because these are two different sessions.

select current_setting('custom.userid'); // empty string

I use EF Code First and manipulate models, not raw queries

using (var context = new MyDbContext())
{
    context.Database.ExecuteSqlCommand("set session custom.userid  = 'NAME';");
    context.MyTables.Add(new MyTable
    {
        Code = 'abc',
        Value = 1
    });
    context.SaveChanges();
}

This doesn't work either, because there are 2 different sessions. As far as I understand, EF creates raw SQL query inside its internals and it is executed in separate session.

Is it possible to access these internals (write hook function or somehow) to add "set session" query to any query issued by EF?

p.s. A possible solution is to use set local (not session) and create additional transaction (if not exist). But i'd like to avoid create transaction just to pass some data.

public class MyDbContext : DbContext
{
    public override int SaveChanges()
    {
        IDbContextTransaction trans = null;

        try
        {
            if (Database.CurrentTransaction == null)
            {
                trans = Database.BeginTransaction();
            }
            Database.ExecuteSqlCommand("set LOCAL custom.userid = 'test987';");
            return base.SaveChanges();
        }
        finally
        {
            trans?.Commit();
        }
    }
}
Doctor Coder
  • 1,001
  • 1
  • 10
  • 17
  • Have you tried put the both ExecuteSqlCommand inside a Transaction? Maybe it can works. – Thiago Araújo Jul 22 '19 at 20:34
  • Yes, `set local` (not session) inside the same transaction works. But i'd like to avoid to create additional transaction if possible. – Doctor Coder Jul 23 '19 at 09:00
  • You can run both sql commands separated by ';' in one `ExecuteSqlCommand` call. – Gert Arnold Jul 23 '19 at 09:16
  • I think you have to consider to use Transactions, not just because your problem. Using transactions is a good programming practice. – Thiago Araújo Jul 23 '19 at 12:17
  • Have you looked at this other stackoverflow question? https://stackoverflow.com/questions/42587984/can-i-fire-an-event-on-connect-database-in-entity-framework-core It looks like an answer to this question. – GMK Jul 01 '20 at 22:08

0 Answers0