简体   繁体   中英

Using SESSION_CONTEXT in SQL from an MS Access VBA frontend

I am migrating a MS Access back end database into SQL server.

The existing MS Access front end needs to be be retained.

I am connecting the Access front-end to the SQL database using a service account so that individual users have no direct access to SQL.

I want to record UserId's on record Add and Update actions, but I do not want to have to specify the fields on every call.

I have a hidden table open in Access to maintain a persistent connection to the SQL database.

I created a Session Context object with the UserId in Access using a Sub I call on Access startup, and I have even called the Sub directly before running the record insert.

Sub SqlSetUser()
Dim qdef As DAO.QueryDef

Set qdef = CurrentDb.CreateQueryDef("")
qdef.Connect = CurrentDb.TableDefs("dbo_User").Connect
qdef.SQL = "EXEC sys.sp_set_session_context @key = N'UserId', @value = '" & GetUser() & "';"
qdef.ReturnsRecords = False  ''avoid 3065 error
qdef.Execute

End Sub

I created a trigger in a SQL table to extract the UserId and add it to the record being added with a similar trigger to handle updates;

CREATE   TRIGGER [dbo].[ReferenceItemAdd]
on [dbo].[ReferenceItem]
FOR INSERT
AS
BEGIN
    SET NOCOUNT ON;
    declare @UserId as int = try_cast((Select SESSION_CONTEXT(N'UserId')) as int)
    UPDATE ReferenceItem set AddDate = getdate(), AddUserId = @UserId
    from INSERTED i, ReferenceItem a
    where i.ReferenceItemId = a.ReferenceItemId
    SET NOCOUNT OFF;
END

It only works if I stop the code via a breakpoint and then continue . If I allow the code to run the record is inserted, and the AddDate is set correctly by the trigger but the UserId comes back with NULL.

How can the UserId be made accessible for a trigger in MS-SQL from an MS-Access front-end?

I don't grasp your notes about increased security here?

If you have a client web browser, and a web server, then you certainly have a web server that can update the SQL database with a service account because you have a WHOLE web server between the client and the SQL database.

You have NONE of the above.

Eg:

qdef.Connect = CurrentDb.TableDefs("dbo_User").Connect
qdef.SQL = "EXEC 

Right, so you have linked tables and above is a connection string that is directly hitting the database, and even able to execute stored procedures. I assume this connection is the SAME one used by the linked tables? (anyway, we can leave the supposed security issue for another day – what you have here is plane jane linked tables, and they are directly updating the database, and even able to execute stored procedure code as per your above example.

Next up:

We assume one SQL logon is being used here?

Your code should work, what looks wrong is this:

declare @UserId as int = try_cast((Select SESSION_CONTEXT(N'UserId')) as int)

Why are you casting the above to a int? Is not GetUser() you set a string? (your example code has ' ' around the text – so it assumed to be a character type.

And it is a direct variable assignment – you don't need the select.

You should be using:

 DECLARE @UserID as varchar(25) = CAST(SESSION_CONTEXT(N'UserId') AS varchar(25))

I don't know if the session will remain constant for all the linked tables. I would 100% ensure that all linked tables have the exact same connection string. You should be able to execute your code one time on startup to set that session value. However, I not 100% sure that a single session will always be used here (you can come back and confirm this - as I am rather interested if this is the case).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM