How can I org-roam-protocol capture to separate Roam profiles, e.g. using .dir-locals.el, with a single target org-roam-capture-ref-template id?

My suggestion above is it to define two different protocols: org-protocol-work:// and org-protocol:// or something like this. The rest should be controlled by the OS level setting that you see Org-roam manual and Org manual. You’d have two different bookmarklet with a call to the emacsclient with different options (manual):

You can run multiple Emacs servers on the same machine by giving each one a unique server name, using the variable server-name. For example, M-x set-variable RET server-name RET “foo” RET sets the server name to ‘foo’. The emacsclient program can specify a server by name, using the ‘-s’ or the ‘-f’ option (see emacsclient Options), depending on whether or not the server uses a TCP socket (see TCP Emacs server).

Alternatively, you may be able to work with a single org-protorol:// like the normal way, but create your custom function, like my/org-roam-protocol-open-ref-work and create a corresponding JS bookmarklet like roam-ref-work. And set org-protocol-protocol-alist (see how org-roam-protocol.el does this. This may be easier.

You should be able to copy the function from org-roam-protocol and let-bind your work-specific (or personal-specific) DB location and org-roam-directory.

I am assuming you can code Elisp – no need to be an expert.

I hope what I am saying above makes sense to you.