I see two different things as a summary of your view:
Use redis as second level cache above NHB. This make perfect sense as SLC stores separated fields of objects and redis is key/value store. As I remember, SLC contain results of scalar queries or mapped and fetched objects but what's important, the data are taken (cached) from performed queries.
IMHO if you would use redis this way, all cached values must result from NHB queries. This brings you some kind of transaction atomicity, how did you already described, but as far as I know, we found couple bugs when SCL returned stale data or data from uncommitted transactions.
Note that this approach says that someone (NHB) still needs to somehow guarantee business transaction between RDBMS and Redis, which is not simple and buggy.
Also note that SLC itself is not incredibly fast pattern. As SLC contain field of object and not object itself, every hit results into new object creation. So what happen is fetching data from Redis instead of resultset obtained from executed SQL query. So, when you use prepared statements and RDBMS typically makes caching for you, you can find out that this does not bring very large performance improvement for you.
Redis as a separated business store. You managed data completely on you own, you can make their computation within native (C#) code (contrary to SQL query or mapped object). You need to guarantee fresh data and some transaction approach.
What I would choose? Separated redis. Why?
- Second level cache along with mapping puts some contract to you as the content results from queries or mapped objects. You can't manage or use Redis on your own. Especially your cached data are coupled/tight to those queries, not to some API (interfaces) and some kind of service (as I would design it)
- You can make computation of you data in your own code.
- SLC approach seems buggy for me and often it was very hard to find these bugs.